GridBagLayout 에 대한 정리 1
GridBagLayout 에 대한 정리 2

GridBagLayout을 복잡하게 만드는 이유를 꼽자면 다음을 거론할 수 있다.

1. 서로 다른 맥락의 설정값들이 모두 int 타입으로 되어 있다.

2. 레이아웃 설정이 각각의 컴포넌트 단위로 실행되어서 코드가 지나치게 길어진다.

이 두가지 문제를 해결하기 위해서 간단한 유틸을 만들었는데 이를 통해서 코드의 양을 2/3 정도 줄일 수가 있다. 무엇보다도 "컴포넌트 단위"가 아니라  "행 단위"로 처리를 하기 때문에 중간에 다른 컴포넌트를 끼워넣거나 수정하기에 용이하다.

GridBagLayout Utility Class

구성하고자 하는 화면은 대충 다음과 같은 형태이다.

원래는 종이에 그린 것.

종이에 구성하려는 화면을 위와같이 그린 후 좌표값을 입력하기 위해 구획을 나누어 본다. 여기서는 대강 아래와 같이 구간을 나눴는데 Address 입력란은 세로로 2칸을 차지하도록 했고 instroduction 입력창은 가로로 세 칸, 세로로 2칸을 차지하도록 했다.

구획을 나눠서 좌표값 부여

각각의 좌표값이 gridx, gridy에 해당되나 utility 클래스에서는 따로 입력하지 않기 때문에 행 단위로 화면이 잘 구성되었는지 확인하는 정도로만 참조하게 된다.

우선 아래와같이 유틸리티 클래스의 인스턴스를 하나 만든다.
GbUtil 클래스는 컨테이너 인스턴스를 파라미터로 전달받는데, 앞으로 추가하는 컴포넌트들의 부모 클래스가 된다. 그리고 defaultWeightX로 column 별로 할당될 공간의 비율을 정한다. 두번째, 네번째 행을 0.5로 지정함으로써 여기에 해당되는 컴포넌트들은 가변폭이 된다.

우선 맨 첫줄에 있는 nameLabel, nameField, phoneLabel, phoneField 를 추가하는 코드는 아래와 같다.
addRow(...) 메소드로 한 행을 이루는 컴포넌트들을 한꺼번에 입력한다.

GbUtil에서는 입력된 행을 보고 자동으로 좌표값을 부여해준다.

fill(...) 메소드는 배열 형태로 전달된 현재의 행을 구성하는 컴포넌트 중에 개별적으로 fill 방식을 지정한다. 위에서 2열, 4열에 0.5로 가중치를 주었기 때문에 nameField와 phoneField가 폭이 변할 때 여백을 다 채우도록 지정한다.

한 행의 입력이 다 끝나면 commit(); 을 호출해서 설정을 반영하고 다음 행을 준비하게 된다.

두번 째 행을 입력하는 코드는 다음과 같다.
첫번째 행과 다른 점은 주소를 입력하는 text area의 구획을 가로로 1칸, 세로로 2칸 지정해준 것이다.

u.span(addresScroll, 1, 2);// 2행 1열

세로로 2칸을 할당했으므로 이 여백을 모두 채우려면 fill 값을 BOTH로 지정해서 상하좌우 모두 꽉 채우도록 지정해준다.

u.fill(addresScroll, GbUtil.FILL_BOTH);

세 번째 행의 코드는 다음과 같은데, 2행에서 addressScroll을 2행으로 지정했기 때문에 영향을 받는다.

두 지점을 NULL로


3행의 마지막 열(파란 부분)은 2행에서 addressScroll이 차지했기 때문에 넣을 필요가 없다. (넣어도 안나온다.) 마찬가지로 그 옆의 label도 넣을 필요가 없으므로 세 번째와 네 번째에는 GbUtil.NULL_COMP 를 지정해서 아무 값도 할당하지 않는다고 표시한다.

위에서는 3열과 4열이 맨 마지막이므로 NULL 처리를 하지 않고 앞서 있는 두 개의 컴포넌트(label과 라디오버튼)만 추가해도 별 상관이 없다. 하지만 만일 2행에서 birth와 address의 위치를 바꿔서 addressScroll이 2행 2열로 옮겨간다면 3행 2열에는 NULL 처리를 해줘야지 화면이 깨지지 않는다.

4행과 5행의 코드는 아래와 같은데 5행은 전체 행이 아무런 의미가 없으므로 dummy 행을 넣어서 통과하게 한다.
위에서 dummy행이 필요한 이유는 introduction lable을 위로 올려붙이기 위해서 옆에 있는 introScroll 의 세로 구획을 2칸으로 할당해주었기 때문이다.(1칸으로 하면 text area의 weighty 가 1.0으로 되어 있어서 옆의 label도 같이 공간 전체를 채우게 된다.)

.span(introScroll, 3, 2)

introScroll 이 세로로 2칸을 차지하고 가로로 3칸을 차지하면서 그 다음 5행에는 추가할 컴포넌트가 없다. 만일 dummy 행을 입력하지 않으면 아래에 이어지는 button pannel 이 5행에 추가되는데, 정확하게 introScroll 의 위치와 겹치면서 화면이 깨진다.

마지막 button pannel은 아래와 같다.
button pannel 의 weightx 값을 바로 위에 위치한 text area와 똑같이 지정해 줘서 창의 폭이 변할 때 동적으로 똑같은 너비를 갖게 한다. 그리고 마지막 행 입력 시 commit(true);로 margin을 설정할 힌트를 준다. (commit(true)는 맨 마지막 행을 입력할 때만 호출해야 셀 간의 간격이 제대로 설정된다. 이 부분은 좀 매끄럽지 못해서 나중에 다듬을 필요가 좀 있는 듯..)

이렇게 해서 출력된 화면은 아래와 같다.

대강 비슷하게 나온 화면

컴포넌트가 다닥다닥 붙어있어서 갑갑한 느낌이 드니 여백을 지정해줄 필요가 있다.

우선 가운데 붕 떠있는 Name, Birth, Phone 등을 오른쪽으로 밀착하기 위해서 모든 컴포넌트의 anchor값을 지정해준다.

label이 우로 밀착되었다.

그리고 컴포넌트 사이의 간격을 4픽셀 정도 잡아주면 한결 보기가 좋다.

컴포넌트간 4픽셀

마지막으로 테두리에 10픽셀 정도 여백을 준다.

테두리에 10픽셀

GbUtil 에는 두 가지 종류의 메소드가 있는데, 모든 컴포넌트에 일괄 적용되는 default...(..) 로 시작하는 메소드와 특정 컴포넌트에 설정값을 지정하는 메소드가 있다. 개별 메소드에 적용된 값들이 default...(...) 로 설정한 기본값들보다 우선한다.

컴포넌트에 지정된 값이 있을 경우에 기본값은 무시되는데, 4행에서 .marginBottom(introScroll, 0) 으로 하단 여백을 0으로 설정했기 때문에 defaultSpace(4)로 지정한 4픽셀이 무시되고 위 그림처럼 buttonPanel과 textarea에 여백이 존재하지 않는다.

GbUtil.java

'Dev > Java' 카테고리의 다른 글

[JList] 자바 스윙 JList, ListModel, ListCellRenderer 1  (1) 2010.05.12
GridBagLayout Utility Class  (0) 2010.05.06
[Swing] GridBagLayout에 대한 정리 2  (3) 2010.05.06
Posted by yeori
,