[Swing JTable] JTable 다루기 1

http 연결을 통해서 웹페이지 정보를 테이블에 출력하는 예제를 통해서 JTable의 다양한 요소들의 사용 방법을 확인해본다.

[그림1]구현할테이블


1. Bean 클래스 작성

웹페이지에 대한 http 요청을 보내서 서버 정보, 응답메세지, 웹페이지의 크기 등을 보여주는 bean 클래스를 아래와 같이 정의한다.
HTTP 응답으로부터 읽어들일 수 있는 수많은 정보 중에 간략하게 위의 네가지 property만 지정해본다.

2. TableModel 작성

bean 클래스를 관리할 TableModel을 작성해야 하는데, 여기서는 javax.swing.table.AbstractTableModel 상속해서 구현하는 것만으로 충분하다.
bean 클래스인 PageInfo 타입의 인스턴스를 관리해야하므로

        private ArrayList<PageInfo> pages;

와 같이 array list 를 선언해준다.

그리고 addPageInfo(..) 를 호출했을 때 아래와 같이 리스너에 통보해주는 메소드를 같이 호출해주고 있다.

        fireTableRowsInserted(idx, idx);

idx 위치에 새로운 row가 추가되었음을 등록된 리스너들에게 알려준다. 이 메소드를 호출해주어야 view 레이어에서 통보를 받고 다시 table model로부터 색인값으로 데이터를 얻어내서 화면에 그려주게 된다. (AbstractTableModel을 상속한 것도, 만일 TableModel 인터페이스를 직접 구현한다면 리스너를 등록하거나 뷰 레이어에 직접 접근해야하는 등 할 일이 몇 배로 늘어난다. 가능하면 AbstractTableModel을 상속하는게 좋다.)

위에서는 getValueAt(int, int); 부분이 핵심적인 역할을 한다.

뷰 레이어에서 각각의 테이블 셀을 그릴때 getValueAt(int, int); 를 호출해서 모델 데이터를 가져간다. 뷰와 모델이 메세지를 주고받는 통로이기 때문에 각각의 column에 맞는 프로퍼티 값을 반환하도록 해준다.
row 는 array list 에서 쉽게 얻어낼 수 있고 리스트에서 얻어낸 PageInfo 인스턴스에서 column에 맞게 적절한 getter 메소드를 호출해주면 (row, column) 좌표에 맞는 값을 반환할 수 있다.

그리고 PageInfo 에는 네 개의 property가 정의되어 있으므로 테이블에도 출력할 column의 개수가 네 개로 서로 일치하는게 이치에 맞을 듯하나, 여기서는 TableColumn 정보를 완전하게 제공하므로 이 메소드가 호출될 일이 없다.

TableModel.getColumnCount() 는 사용자가 TableColumn 정보를 제공하지 않았을때 호출된다.

모델의 데이터를 출력하려면 당연히 column 정보를 알야하는데 사용자가 제공하지 않았으니 JTable이 어떻게든 TableColumn 을 만들려고 시도하고, column의 개수를 알아내기 위해서 TableModel.getColumnCount()를 호출한다.column의 개수를 얻어낸 후 그만큼 TableColumn 인스턴스를 만든 후 이 column들을 TableColumnModel에 등록한다.

그러니까 JTable과 TableModel, 그리고 TableColumnModel 모두 getColumnCount() 메소드가 있는데 이 중에서 TableModel.getColumnCount()만이 column을 초기화할때 사용된다.(위에서 말했듯이 사용자가 제대로된 TableColumn을 제공해주면 TableModel.getColumnCount() 는 호출될 일이 없다.)

[그림2]TableColumnModel은 View, TableModel은 Model에 해당

JTable 자체가 워낙에 복잡하다보니까 사용자가 혹시 api 에 익숙치 않아서 TableColumn 을 제대로 제공하지 못할 경우 JTable이 임시 방편으로 일단 출력이나 제대로 되게 해놓자... 뭐 이런 뜻이 담겨 있는 것이다.

JTable을 만들때 table model과 table column model(TableColumn을 관리하는 역할)을 제대로 제공해주면 신경쓰지 않아도 되는 메소드 구현이 바로 TableModel.getColumnCount()이다.(하지만 프로퍼티 개수와 맞추줘서 나쁠건 없으니 네 개로 지정해준 것 뿐..)

http 프로토콜로 페이지를 요청하면 응답이 올때마다 PageInfo 인스턴스를 생성하고 이것을 아래와 같이 table model에 추가해주면 자동으로 테이블에 페이지 정보가 출력된다.(MVC모델의 메커니즘)
MVC에서 모델 부분에 대한 첫번째 구현은 이걸로 끝이다. 일단은 화면에 보여주는 기능만을 구현하고 있어서 나중에 테이블에서 직접 데이터를 수정하려고 할 때에 별도로 구현해야할 메소드가 몇 개 있을 뿐이다.

3. TableColumn 작성

TableColumn의 역할은 View 레이어에서 각각의 테이블 셀을 그릴때 "붓" 역할을 할 renderer와 editor 를 제공해준다. 또한 현재 column의 너비값과 테이블 헤더에 출력된 헤더 정보도 제공한다.

PageInfo에 정의된 네 개의 프로퍼티를 보여줄 것이므로 TableColumn도 네 개를 작성할 것이다. 그런데 PageInfo의 프로퍼티 타입이 String과 long 이어서 별도의 renderer를 지정할 필요는 없다.(JTable 내에서 기본적으로 제공되고 있어서 딱히 손댈게 없음).

그래도 Money라든가 다른 동적인 renderer를 제공해주어야 할 때 다음과 같이 TableColumn을 작성하고 setCellRenderer, setCellEditor 로 등록해주면 사용자가 할 일은 끝이다.
위와같이 각 TableColumn에 column index 를 지정해주고 헤더 메세지를 지정해주면 현재 구현에서 더 할 일은 없다.

4. Page 정보 읽어오기

특정 웹페이지 주소를 통해서 응답 헤더 정보를 얻어내서 PageInfo 인스턴스를 생성하는 코드는 아래와 같다.
여기서 중요한 부분은 아니니 자세한 설명은 생략한다.

5. TableCellRenderer 설정

위의 코드를 조합하면 아래 그림과 같은데 응답 코드가 밋밋해서 눈에 잘 들어오질 않는다.

[그림3]404, 302같은 응답 코드가 눈에 잘 보였으면 좋을

위에서 TableColumn에 기본 renderer 를 전달해줬기 때문인데, renderer를 약간만 변형해서 200이 아닌 코드의 글자 색을 바꿔주는 게 좋을 듯 하다.
그리고 위의 renderer를 response 메세지를 보여주는 TableColumn에 등록해준다.
이제 [그림1]과 같이 응답 코드에 따라서 글자색이 다르게 나온다. 이것을 활용하면 전체 행의 색깔도 다르게 지정해줄 수가 있다.
Posted by yeori
,