자바 플랫폼과 함께 제공되는 표준 레이아웃 관리자 중 하나가 BoxLayout
입니다. 이 관리자를 사용하여 단일 행 또는 열의 구성요소를 컨테이너에 배치할 수 있습니다. 그리 복잡하지 않은 레이아웃 관리자인 듯 하나, Box
및 해당 glue와 strut를 활용하면 충분하리라 생각할 것입니다. 하지만 이것이 전부는 아닙니다. 기본 구성요소의 수직 및
수평 정렬을 통해 컨테이너 내부에서 구성요소의 위치를 더 제어할 수 있습니다. 이 점을 모두 살펴보겠습니다.
BoxLayout은 레이아웃 관리자를 생성하고 이를 Container
와 연결하면 되는 대부분의 레이아웃 관리자와 다릅니다. BoxLayout
구성자에서는 Container
를 레이아웃 관리자의 구성자에 전달하여 각각 다른 구성요소에 대한 참조를 포함해야 합니다. 이 작업이 번거롭게 여겨질 수도 있으므로, Box
컨테이너를 사용하는 경우가 더 많습니다. static
메소드 중 하나를 통해 수평 또는 수직 배열된 Box
를 요청하면 되기 때문입니다.
Box vertical = Box.createVerticalBox();
Box horizontal = Box.createHorizontalBox();
둘 다 배후에서는 BoxLayout
을 사용하면서 추가된 구성요소를 방향에 따라 알맞은 액세스에 배치합니다. 수직 박스는 모든 것을 하나의 열에, 수평 박스는 하나의 행에 배치합니다. BoxLayout
(그리고 Box
)을 GridLayout
과 비교하려면 간단한 설명이 필요합니다. GridLayout
에서 제어하는 컨테이너에 여러 구성요소를 배치할 경우 모든 구성요소는 동일한 크기여야 합니다. BoxLayout
에서는 그렇지 않으며, 구성요소 최대 기본 크기가 인정됩니다.
Box 클래스에서는 두 가지 지원 구성요소를 생성하는데, 고정 크기의 필러 영역인 strut와 확장 가능한 영역인
glue입니다. strut를 사용하면 고정된 간격으로, glue를 사용하면 가용 공간에 따라 확대/축소되는 영역으로 컨테이너에
구성요소를 배치할 수 있습니다. GridBagConstraints
및 GridBagLayout
을 사용하면 동일한 효과를 얻을 수 있으나, 쉽지 않습니다.
이를 확인하기 위해 다음 첫 번째 프로그램에서는 맨 위의 두 구성요소 사이에 25픽셀의 strut를, 맨 아래 두 구성요소 사이에는 10픽셀의 strut를 생성합니다.
import java.awt.*;
import javax.swing.*;
public class VerticalBoxTest {
public static void main(String args[]) {
JFrame frame = new JFrame("Vertical Box");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Box box = Box.createVerticalBox();
box.add(new Button("Top"));
box.add(Box.createVerticalStrut(25));
box.add(new Button("Middle"));
box.add(Box.createVerticalStrut(10));
box.add(new Button("Bottom"));
frame.add(box, BorderLayout.CENTER);
frame.setSize(300, 200);
frame.setVisible(true);
}
}
이 코드를 컴파일하고 실행하여 창 크기가 증감할 때 구성요소의 크기가 어떻게 바뀌는지 확인하십시오. 구성요소 사이의 거리는
바뀌지 않고, 예약된 strut 공간과 일치합니다. 이 예제에서는 곧 나올 구성요소 정렬에 대한 설명을 피하기 위해 JButton
대신 <code>Button</code>을 사용합니다.
수평 박스와 glue를 사용하면 비슷한 결과를 얻지만, 이번에는 strut처럼 고정된 크기를 유지하는 것이 아니라 glue의 크기가 증가하면서 추가 공간을 차지합니다.
import java.awt.*;
import javax.swing.*;
public class HorizontalBoxTest {
public static void main(String args[]) {
JFrame frame = new JFrame("Horizontal Box");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Box box = Box.createHorizontalBox();
box.add(Box.createHorizontalGlue());
box.add(new JButton("Left"));
box.add(new JButton("Right"));
frame.add(box, BorderLayout.NORTH);
box = Box.createHorizontalBox();
box.add(new JButton("Left"));
box.add(Box.createHorizontalGlue());
box.add(new JButton("Right"));
frame.add(box, BorderLayout.CENTER);
box = Box.createHorizontalBox();
box.add(new JButton("Left"));
box.add(new JButton("Right"));
box.add(Box.createHorizontalGlue());
frame.add(box, BorderLayout.SOUTH);
frame.setSize(300, 200);
frame.setVisible(true);
}
}
JButton
구성요소를 사용하는 경우를 살펴보겠습니다.컨테이너 내부의 구성요소가 다른 크기일 경우 또는 컨테이너의 높이/너비가 수직 박스에 필요한 것보다 넓거나 수평 박스에 필요한 것보다 높을 경우, Box/BoxLayout
에서는 흥미로운 상황이 벌어집니다. 즉 긴 열에서 너비가 다른 구성요소는 어떻게 됩니까? 그리고 높이가 다른 구성요소로 이루어진 넓은 행이 있다면 어떻게 됩니까?
여기서 다른 구성요소 정렬 방법이 진가를 발휘합니다. 각 Swing 구성요소에는 X-alignment
설정과 Y-alignment
설정이 있습니다. get/setAlignmentX()
및 get/setAlignmentY()
메소드 덕분입니다. 각 설정의 범위는 0
부터 1.0
까지입니다. BoxLayout
의 방향에 따라 0
은 왼쪽 또는 맨 위 정렬을, 1
은 오른쪽 또는 맨 아래 정렬을 의미합니다. Component
클래스에 사용 가능한 상수가 있으므로, 어떤 값이 오른쪽 및 왼쪽 정렬인지 알 필요는 없습니다. 그러나 그 사이에 뭔가를 둘 것인지 안다면 도움이 됩니다.
수직 박스에서 크기가 다른 버튼의 오른쪽, 왼쪽 및 가운데 특성을 보여주기 위해, 다음 프로그램에서는 각각 왼쪽, 가운데 및 오른쪽 정렬 버튼이 있는 박스 3개를 생성합니다.
import java.awt.*;
import javax.swing.*;
public class AlignX {
private static Container makeIt(String labelChar, float alignment) {
Box box = Box.createVerticalBox();
for (int i=1; i<6; i++) {
String label = makeLabel(labelChar, i*2);
JButton button = new JButton(label);
button.setAlignmentX(alignment);
box.add(button);
}
return box;
}
private static String makeLabel(String s, int length) {
StringBuffer buff = new StringBuffer(length);
for (int i=0; i<length; i++) {
buff.append(s);
}
return buff.toString();
}
public static void main(String args[]) {
JFrame frame = new JFrame("X Alignment");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container panel1 = makeIt("L", Component.LEFT_ALIGNMENT);
Container panel2 = makeIt("C", Component.CENTER_ALIGNMENT);
Container panel3 = makeIt("R", Component.RIGHT_ALIGNMENT);
frame.setLayout(new FlowLayout());
frame.add(panel1);
frame.add(panel2);
frame.add(panel3);
frame.pack();
frame.setVisible(true);
}
}
다음은 이를 확인하기 위한 프로그램입니다.
import java.awt.*;
import javax.swing.*;
public class AlignX2 {
public static void main(String args[]) {
JFrame frame = new JFrame("X Alignment");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Box box = Box.createVerticalBox();
JButton button = new JButton("LL");
button.setAlignmentX(Component.LEFT_ALIGNMENT);
box.add(button);
button = new JButton("CC");
button.setAlignmentX(Component.CENTER_ALIGNMENT);
box.add(button);
button = new JButton("RR");
button.setAlignmentX(Component.RIGHT_ALIGNMENT);
box.add(button);
frame.add(box, BorderLayout.CENTER);
frame.setSize(300, 200);
frame.setVisible(true);}
}
이를 입증해 주는 화면입니다.
다른 방향의 작업에서는 맨 위 정렬의 경우 구성요소의 맨 위가 가상의 중심선에, 즉 가운데 아래에 옵니다.
이런 식으로 정렬을 혼합하더라도 제대로 작동하지만, 익숙해지는 데 시간이 걸립니다. 모든 정렬이 동일하지 않는 한 정렬이 예상한 위치에 오지 않을 수도 있으며, 컨테이너 중심선이 아니라 컨테이너의 경계에 맞춰지기 때문입니다.
아직도 잘 이해되지 않는다면 이전의 프로그램을 수정하여 x
및 y
정렬의 조합을 더 시도해 보십시오. 물론 모든 시도가 생각대로 되지 않는다면 언제든지 GridBagLayout
을 사용하면 됩니다.
이 글의 영문 원본은
http://blogs.sun.com/CoreJavaTechTips/entry/getting_to_know_boxlayout
에서 보실 수 있습니다.