• Home
  • About
    • Young's Github Pages photo

      一日不作一日不食

    • About
    • Github
  • Posts
    • All Posts
    • All Tags
  • Projects

Java 정리 25

17 Dec 2018

Reading time ~7 minutes

Java 정리 25 - JTable, JTabbedPane, Exception Handling(1)


JTable

  • MVC Pattern이 적용된 Component
// 1. DefaultTableModel 생성
// - 컬럼명 설정 배열 : String[] columnNames = {"컬럼명",...};
// - 데이터 설정 배열 : String[][] rowData = { {값,.. }, {값,.. },.. };
DefaultTableModel dtm = new DefaultTableModel(rowData, columnNames);

// 2. JTable 생성
JTable jt = new JTable(dtm);

// 3. Scrollbar 설정
// - 스크롤바 추가 안하면 컬럼의 이름이 보이지 않는다.
JScrollPane jsp = new JScrollPane(jt);
// MVC Pattern이 적용된 class
@SuppressWarnings("serial")
public class UseJTable extends JFrame implements ActionListener  {
  private JTable jt;
  private JButton btnAdd;
  private DefaultTableModel dtm;
  private UseJTable ujt;
  
  public UseJTable() {
    super("JTable 연습");
    ujt = this;
    
    // 1. 데이터를 관리하는 Model 클래스 생성
    String[] columnName =  {"번호","이름","주소","이메일"};
    String[][] rowData = {
        { "1","이재찬","인천시  소래동","chan@test.com" },
        { "2","정택성","서울시  구로동","teack@test.co.kr" },
        { "3","이재현","경기도  안양시","hyun@test.com" } };
    
    // 수정불가능하도록 변경
    dtm = new DefaultTableModel(rowData, columnName) {
      @Override
      public boolean isCellEditable(int row, int  column) {
        return false;
      }
    };
    
    
    // 2. 데이터를 보여주는 View 클래스 생성
    jt = new JTable(dtm);
    // 테이블 컬럼의 크기 변경 : 컬럼은 하나의 필드  넓이를 변경하면
    // 하위 모든 컬럼은 동일한 크기를 적용받음
    // 컬럼크기변경 1. 컬럼을 얻는다.
    TableColumn tcNum = jt.getColumnModel().getColumn(0);
    
    // 컬럼크기변경 2. 컬럼의 크기 변경.
    tcNum.setPreferredWidth(50);
    
    // 이렇게 한줄로 처리 가능
    jt.getColumnModel().getColumn(1).setPreferredWidth(100);
    jt.getColumnModel().getColumn(2).setPreferredWidth(200);
    jt.getColumnModel().getColumn(3).setPreferredWidth(150);
    
    // 행의 높이 변경
    jt.setRowHeight(29);
    
    btnAdd =  new JButton("데이터 추가");
    JPanel jp = new JPanel();
    jp.add(btnAdd);
    
    // 3. Column의 이름과 Scrollbar를 사용할 수 있도록  JScrollPane에 배치
    JScrollPane jsp = new JScrollPane(jt);
    
    add(BorderLayout.CENTER, jsp);
    add(BorderLayout.SOUTH, jp);
    
    btnAdd.addActionListener(this);
    
    UseJTable.TableEvt te = this.new TableEvt();
    jt.addMouseListener(te);
    
    setBounds(300, 250, 500, 200);
    setVisible(true);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  }
  
  @Override
  public void actionPerformed(ActionEvent e) {
    String inputData =  JOptionPane.showInputDialog("데이터입력\n예)번호,이름,주소,이메일");
    
    String[] tempData = inputData.split(",");
    
    if (tempData.length != 4) {
      JOptionPane.showMessageDialog(this,
        "입력 데이터의 형태는 \n  번호,이름,주소,이메일이어야 합니다.",
        "입력 오류",  JOptionPane.ERROR_MESSAGE);
      return;
    }
    
    // 입력된 데이터를 화면에 보여주기 위해  DefaultTableModel에 추가
    // Object이 String의 부모이므로, String은 Object의  자식이므로 매개변수로 들어갈 수 있음
    dtm.addRow(tempData);
  }
  ///////////////// inner class 시작  ////////////////
  public class TableEvt extends MouseAdapter {
    @Override
    public void mouseClicked(MouseEvent e) {
      int selectedRow = jt.getSelectedRow();
      
      int flag = JOptionPane.showConfirmDialog(ujt,
              "예를 누르면 조회, 아니오를 누르면  삭제");
      
      switch(flag) {
      case JOptionPane.OK_OPTION:
        int columnCount = jt.getColumnCount();
        
        // 선택된 행의 정보를 가져와서 Dialog로  보여주기
        String selectedVal;
        StringBuilder viewData = new  StringBuilder();
        for(int i=0; i<columnCount; i++) {
          selectedVal =  (String)jt.getValueAt(selectedRow, i);
          viewData.append(selectedVal).append("\n");
        }
        
        JOptionPane.showMessageDialog(ujt,  viewData, "행 결과", JOptionPane.PLAIN_MESSAGE);
        break;
      case JOptionPane.NO_OPTION:
        // 선택한 행을 지우기
        switch(JOptionPane.showConfirmDialog(ujt,  "정말 삭제하시겠습니까?")) {
        case JOptionPane.OK_OPTION:
          dtm.removeRow(selectedRow);
          break;
        }
      }
    }
  }
  ///////////////// inner class 끝  ////////////////
  public static void main(String[] args) {
        new UseJTable();
  }
}

01

... 
JTable jt = new JTable(dtm);
// 테이블 컬럼의 크기 변경 : 컬럼은 하나의 필드  넓이를 변경하면
// 하위 모든 컬럼은 동일한 크기를 적용받음
// 컬럼크기변경 1. 컬럼을 얻는다.
TableColumn tcNum = jt.getColumnModel().getColumn(0);

// 컬럼크기변경 2. 컬럼의 크기 변경.
tcNum.setPreferredWidth(50);

// 이렇게 한줄로 처리 가능
jt.getColumnModel().getColumn(1).setPreferredWidth(100);
jt.getColumnModel().getColumn(2).setPreferredWidth(200);
jt.getColumnModel().getColumn(3).setPreferredWidth(150);
...

02

// 행의 높이 변경
jt.setRowHeight(29);

03

  • 테이블에 발생한 이벤트는 MouseListener를 사용
    • 이너클래스로 구현
UseJTable.TableEvt te = this.new TableEvt();
jt.addMouseListener(te);
...
///////////////// inner class 시작  ////////////////
public class TableEvt extends MouseAdapter {
  @Override
  public void mouseClicked(MouseEvent e) {
    int selectedRow = jt.getSelectedRow();
    int columnCount = jt.getColumnCount();
    
    // 선택된 행의 정보를 가져와서 Dialog로  보여주기
    String selectedVal;
    StringBuilder viewData = new StringBuilder();
    for(int i=0; i<columnCount; i++) {
      selectedVal =  (String)jt.getValueAt(selectedRow, i);
      viewData.append(selectedVal).append("\n");
    }
    JOptionPane.showMessageDialog(ujt, viewData,  "행 결과", JOptionPane.PLAIN_MESSAGE);
  }
}
  • 이너클래스에서 부모의 창을 전해줄 때 아래와 같이 구현
    • 자기 인스턴스의 주소를 저장하는 인스턴스변수를 만들고
    • 그 인스턴스변수를 사용하여 부모창을 식별할 수 있음
private UseJTable ujt;

public UseJTable() {
      super("JTable 연습");
      ujt = this;

...

    // inner 클래스 안에서 현재 창(JFrame)위로 Dialog를 띄울 때, 이렇게 주소 전달
    JOptionPane.showMessageDialog(ujt, rowData, "행  결과", JOptionPane.PLAIN_MESSAGE);
    System.out.println(rowData);
  }
  ...
}
  • 테이블 Cell의 수정 막기
    • DefaultTableModel의 isCellEditable은 무조건 true를 반환함
      • false를 반환하게 만들어야 편집이 안됨
    • 익명클래스로 Override해서 false만 반환하도록 만들면 수정이 불가능해짐
// 수정불가능하도록 변경
dtm = new DefaultTableModel(rowData, columnName) {
  @Override
  public boolean isCellEditable(int row, int  column) {
    return false;
  }
};
  • 변경과 삭제는 무조건 물어봐야 한다.
///////////////// inner class 시작  ////////////////
public class TableEvt extends MouseAdapter {
  @Override
  public void mouseClicked(MouseEvent e) {
    int selectedRow = jt.getSelectedRow();
    
    int flag = JOptionPane.showConfirmDialog(ujt,
                "예를 누르면 조회, 아니오를 누르면  삭제");
    
    switch(flag) {
    case JOptionPane.OK_OPTION:
      int columnCount = jt.getColumnCount();
      
      // 선택된 행의 정보를 가져와서 Dialog로  보여주기
      String selectedVal;
      StringBuilder viewData = new  StringBuilder();
      for(int i=0; i<columnCount; i++) {
            selectedVal =  (String)jt.getValueAt(selectedRow, i);
        viewData.append(selectedVal).append("\n");
      }
      
      JOptionPane.showMessageDialog(ujt,  viewData, "행 결과", JOptionPane.PLAIN_MESSAGE);
      break;
    case JOptionPane.NO_OPTION:
      // 선택한 행을 지우기
      switch(JOptionPane.showConfirmDialog(ujt,  "정말 삭제하시겠습니까?")) {
      case JOptionPane.OK_OPTION:
        dtm.removeRow(selectedRow);
        break;
      }
    }
  }
}
///////////////// inner class 끝  ////////////////

Tab

  • 한정적인 공간에서 여러 창을 번갈아가며 보여줄 때
  • JTabbedPane사용
// 1. 생성
JTabbedPane jtp = new JTabbedPane();

// 2. 디자인을 가진 Container Component 추가
JPanal jp = new JPanel();
 ... // jp에 컴포넌트들 붙이고 탭에 더한다.
jtp.add(jp);
@SuppressWarnings("serial")
public class UseJTab extends JFrame {
  
  public UseJTab() {
    super("Tab");
    
    // 1. 탭을 추가할 수 있는 객체를 생성
    JTabbedPane jtp = new JTabbedPane();
    
    // 2. 각 탭에 들어갈 컴포넌트를 생성.
    ImageIcon ii = new  ImageIcon("C:/.../ebichuGif.gif");
    JLabel jl = new JLabel(ii);
    
    // 두번째 탭에 들어갈 컴포넌트
    JPanel jp = new JPanel();
    jp.add(new JLabel("이름"));
    jp.add(new JTextField(30));
    jp.add(new JButton("입력"));
    
    JPanel tab2 = new JPanel();
    tab2.setLayout(new BorderLayout());
    
    jp.setBorder(new TitledBorder("입력데이터"));
    
    JTextArea jta = new JTextArea();
    JScrollPane jsp = new JScrollPane(jta);
    jsp.setBorder(new TitledBorder("결과창"));
    
    tab2.add("North", jp);
    tab2.add("Center", jsp);
    
    jtp.add("처음탭", jl);
    jtp.add("두번째 탭", tab2);
    jtp.add("세번째 탭", new JButton("클릭"));
    
    // 배치
    add("Center",jtp);
    
    setBounds(300, 200, 600, 600);
    setVisible(true);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  }
  public static void main(String[] args) {
    new UseJTab();
  }
}

04


Exception Handling(예외처리)

  • 프로그램 동장 중에 발생할 수 있는 가벼운 Error가 발생했을 때 그에 대한 대비코드를 만들어 두는 것
  • 모든 Exception과 Error의 부모는 Throwable 클래스
    • Error는 발생하면 프로그램이 더 이상 동작을 할 수 없다.
    • Exception은 발생하면 프로그램은 계속하여 동작할 수 있다.
  • Compile Exception과 Runtime Exception 두가지로 구분
    • Compile Exception은 개발자가 반드시 처리해야하는 예외
    • Runtime Exception은 JVM이 자동으로 처리해주는 예외
  • try~catch, throws, throw 로 처리
  • System.err - 표준 에러출력 스트림
  • 상속관계

05

  • Compile time, Runtime Exception
    • 컴파일의 목적은 bytecode를 만드는 것.
    • 컴파일 예외처리는 bytecode가 제대로 생성되도록 코드를 처리하는 것.
      • 개발자가 코드 작성시 컴파일 예외처리 코드를 명시
    • 실행할때 발생하는 에러 = RuntimeException
      • 개발자의 손을 벗어난 class가 memory를 사용할 때 발생하는 예외

06

// 예외처리문법
try {
    예외발생 예상코드;
} catch(예외처리클래스명 객체명) {
    // 예외발생시 그 예외를 처리할 코드
    // catch는 여러개 작성가능
    // 부모클래스가 가장 위에 올라오면 안된다.(아래 catch에서 error발생)
    // 부모는 모든 예외를 다 잡을 수 있다.(Exception)
} finally {
    // 반드시 실행되어야할 코드
}
  • 아래 예제에서는 3개의 RuntimeException이 발생
    • ArrayIndexOutOfBoundsException
    • ArithmeticException
    • NumberFormatException
public class UseRuntimeException {
     
  public static void main(String[] args) {
  
    int num1 = Integer.parseInt(args[0]);
    int num2 = Integer.parseInt(args[1]);
    int result = 0;
    
    result = num1/num2;
    
    System.out.println(num1+" / "+num2+" = "+result);
  }
}

07

catch문 안에서 예외처리

  • 에러 출력 스트림 사용을 권장(의미적으로)
  • 일반 사용자에겐 예외 내용을 알려줄 필요가 없음
System.err.println("예외발생시 제공할 내용들");

// 1. 간단한 메시지만 출력할 때
예외처리객채명.getMessage();

System.err.println(e.getMessage());

// 2. 예외처리객체명과 메시지 출력
예외처리객체명 // 예외처리객체명.toString()과 동일

// 3. 자세한 메시지를 출력 (예외와 관련있는 모든 클래스가 다 출력)
예외처리객체명.printStackTrace();
public class UseRuntimeException {
  
  public static void main(String[] args) {
  
    try {
      int num1 = Integer.parseInt(args[0]);
      int num2 = Integer.parseInt(args[1]);
      
      int result = 0;
      
      result = num1/num2;
      
      System.out.println(num1+" / "+num2+" =  "+result);
    } catch (ArrayIndexOutOfBoundsException aioobe) {
      System.err.println("배열의 인덱스가  잘못되었습니다.");
      System.err.println("예외의 이유 :  "+aioobe.getMessage());
      System.err.println("예외처리 클래스명과 이유 :  "+aioobe);
      aioobe.printStackTrace(); // 자세한 예외
    } catch (ArithmeticException ae) {
      System.err.println("0으로 나눌 수 없습니다.");
      System.err.println("예외의 이유 :  "+ae.getMessage());
      System.err.println("예외처리 클래스명과 이유 :  "+ae);
      ae.printStackTrace(); // 자세한 예외
    } catch (NumberFormatException nfe) {
      System.err.println("입력값이 숫자형태가  아닙니다.");
      System.err.println("예외의 이유 :  "+nfe.getMessage());
      System.err.println("예외처리 클래스명과 이유 :  "+nfe);
      nfe.printStackTrace(); // 자세한 예외
    } catch (Exception e) {
      System.err.println("개발자가 인지하지  못한예외.");
      e.printStackTrace();
    } finally {
      System.out.println("반드시 실행되어야할  코드");
    }
  }
}

08

  • 예외를 왜 나눠서 처리할까?
    • 예외가 발생했을 때 식별해서 다르게 처리하려고

숙제풀이

1-1. 프로그램이 시작되면 아래와 같은 메뉴를 제공한다.

09

1-2. 1번을 넣고 입력을 누르면 inputDialog를 띄워준다.

10

  • 입력버튼이 눌려지면 입력값을 VO에 넣고
    • VO를 List에 추가한 후 메뉴를 보여준다.
  • 값을 잘못 넣었을 시 MessageDialog 보여주기

1-3. 출력(2)를 입력하면, 쌓여있는 List의 크기를 재서 0이면 Message Dialog로 “데이터가 없습니다.” 를 출력. 데이터가 하나 이상인 경우 아래와 같이 출력하고 확인버튼이 눌리면 다시 메뉴를 제공

11

// MessageDialog에 JTextArea 넣기 예제
public class Test2 {
  
  public static void main(String[] args) {
    
    // Message Dialog에 JTextArea넣기
    // 1.JTextArea 생성(컬럼수, 행수 설정해서 만듦)
    JTextArea jta = new JTextArea(10,40);
    jta.setEditable(false);    // 편집막
    jta.append("asdjflsjdklfjls"); // 값 덧붙여 넣기
    
    // 2.
    JScrollPane jsp = new JScrollPane(jta);
    
    // 3. Message Dialog의 두번째 매개변수에 컴포넌트를  넣기
    JOptionPane.showMessageDialog(null, jsp);
  }
}

12

1-4. 3이 입력되면 프로그램을 종료

14

숙제풀이1-1 DataVO class

숙제풀이1-2 ProcessRun class

숙제풀이1-3 Process class

13



Java