Swing

  • Java Application에서 사용되는 GUI(Graphic User Interface)를 제공하는 추상적으로 정의된 도구(컴포넌트) 모음
  • Container
    • 다른 컴포넌트들을 배치하기 위한 컴포넌트
    • Container는 다른 Container를 포함할 수 있고 나중에 복합적인 Layout을 구성할 수 있게 한다.
    • JFrame: 독립적으로 사용될 수 있으며 타이틀과 사이즈를 조절할 수 있는 버튼을 가짐
    • JPanel: 반드시 다른 Container에 포함되어아 하며 복합적인 레이아웃 구성에 사용

Layout과 LayoutManager

  • Layout: Component들을 Container에 어떻게 배치할 것인가
  • LayoutManager: Container별로 Component의 위치와 크기, 배치 방식을 결정하는 객체

  • FlowLayout
    • JPanel의 기본 LayoutManager
    • 요소를 가로로 물 흐르듯이 배치
  • BorderLayout
    • JFrame의 기본 LayoutManager
    • 특별한 영역 즉, North, South, West, East, Center에 각각의 컴포넌트를 배치한다.
      • component들을 배치할 때는 영역을 지정(BorderLayout.CENTER or “Center”)
      • 사용하지 않는 공간의 크기가 0*0이 되고 Center가 기본이다.
      • 각각의 영역에는 하나의 Component를 담을 수 있고 중복해서 담을 경우는 마지막에 담은 컴포넌트만 보인다.
      • 크기를 조절할 때 North와 South는 좌우로, East와 West는 상하로만 늘어난다. Center는 양방향
  • Layout 설정
    • 생성자 또는 setLayout 메소드로 layout 변경 가능 ```java JPanel panel = new JPanel(); // FlowLayout panel.setLayout(new BorderLayout()); // BorderLayout

    JPanel panel2 = new JPanel(new GridLayout()); // GridLayout ```

  • 복합적인 Layout 구성
    • container 안에 또다른 Container를 배치하는 형태로 복합적인 Layout 구성

Event Handling

이벤트 처리 모델(Delegation Model)

  • 위임형 모델
  • 실제로 이벤트가 일어나는 것은 component 이지만 거기서 처리되는 것이 아니라 이벤트 리스너를 등록시킨 후 위임 받은 handler 클래스 내에서 이벤트 처리

    이벤트 처리 클래스

  • XX Listener
    • 이벤트 처리에 대한 메서드들을 정의한 인터페이스로 handler는 이 인터페이스를 구현
    • 하나의 component에 여러 개의 event handle를 붙일 수 있다.’
      • implements ActionListenger, WindowListener
  • XXEventAdapter
    • Listener를 implements할 경우 사용하지도 않는 이벤트 핸들러까지 다 구현해야 하는 단점
    • xxxEventAdapter implements XXListener
      • 해당 메서드들을 모조뢰 구현해 놓은 class, 구현 내용은 비어있는 {}
      • 상속받은 후 필요한 것만 override하면 된다.



// extends JFrame !!!!
private static final long serialVersionUID = 1L;
private JLabel lNum1, lNum2, lCorrectCnt, lWrongCnt;
private JTextField tfAns;
private int answer;

public static void main(String[] args) {
    LayoutTest lt = new LayoutTest();
    lt.launchUi();
}

private void launchUi() {
    this.add(new JLabel("구구단을 외자!"), BorderLayout.NORTH);

    makeResultPanel();
    makeProblemPanel();

    // Frame 기본 설정
    this.setTitle("layout test");
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.pack();
    this.setVisible(true);
}

private void makeProblem() {
    Random rand = new Random();
    int num1 = rand.nextInt(9) + 1;
    int num2 = rand.nextInt(9) + 1;
    this.answer = num1 * num2;
    lNum1.setText(num1 + "");
    lNum2.setText(num2 + "");
    tfAns.setText("");        
}

private void makeResultPanel() {
  JPanel panel = new JPanel();

  panel.add(new JLabel("정답 개수: "));
  lCorrectCnt = new JLabel("0");
  panel.add(lCorrectCnt);
  panel.add(new JLabel("오답 개수: "));
  lWrongCnt = new JLabel("0");
  panel.add(lWrongCnt);

  this.add(panel, BorderLayout.SOUTH);
}



private void makeProblemPanel() {
  JPanel panel = new JPanel();

  lNum1 = new JLabel();
  lNum2 = new JLabel();

  panel.add(lNum1);
  panel.add(new JLabel("*"));
  panel.add(lNum2);
  panel.add(new JLabel("="));

  tfAns = new JTextField(10);
  panel.add(tfAns);

  makeProblem();
  tfAns.addKeyListener(new KeyAdapter() {
    @Override
    public void keyReleased(KeyEvent e) { // 눌리고 올라오는 순간
      if(e.getKeyCode() == 10) {
        int val = Integer.parseInt(tfAns.getText());
        if(val == answer) {
          int pre = Integer.parseInt(lCorrectCnt.getText());
          lCorrectCnt.setText(pre + 1 + "");
        } else {
          int pre = Integer.parseInt(lWrongCnt.getText());
          lWrongCnt.setText(pre + 1 + "");
        }
        makeProblem();
      }
    }
});

    this.add(panel, BorderLayout.CENTER);
}
JTable
JTable table = null;

// table의 데이터를 관리하는 객체
DefaultTableModel model = null;
// 테이블 구성
table = new JTable();
String[] header = {"랭킹", "제목", "개봉일", "누적관객"};
model = (DefaultTableModel) table.getModel();
model.setColumnIdentifiers(header);
버튼이 눌렸을 때, 테이블 업뎃
button.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        // 기존 자료 삭제
        model.setRowCount(0);
        
        // 새로운 자료 조회
        BoxOfficeDomParser parser = new BoxOfficeDomParser();
        List<BoxOffice> list = parser.getBoxOffice();
        for (BoxOffice info : list) { // table setting
            model.addRow(new Object[] {info.getRank(), info.getMovieNm(), info.getOpenDt(), info.getAudiAcc()});
        }
        // model의 데이터가 변경되었음을 알림
        model.fireTableDataChanged();
    }
});
table이 클릭되었을 때
table.addMouseListener(new MouseAdapter() {
      @Override
      public void mouseClicked(MouseEvent e) {
        int row = table.getSelectedRow(); // 선택된 row 가져오기
        String name = model.getValueAt(row, 1).toString();
        JOptionPane.showMessageDialog(BoxOfficeUi.this, "선택된 영화 정보: " + name);
      }
});