배치관리자(Layout Manager)
-----------------------------
오라클자바커뮤니티에서 설립한 오엔제이프로그래밍
실무교육센터
(오라클SQL, 튜닝, 힌트,자바프레임워크, 안드로이드, 아이폰, 닷넷 실무전문 강의)
Component가 컨테이너에 배열되는 방식을 결정 합니다.
모든 컨테이너는 기본 Layout Manager를 가집니다.
Container는 다른 Component를 포함할 수 있는 최소의 클래스이고 java.awt.container 클래스를 상속해야 합니다.
Container를 상속하지 않은 일반 Component에는 Layout Manager가 등록될 수 없습니다.
Frame, Window, Panel등은 Layout Manager를 설정할 수 있으며 이렇게 설정된 Layout Manager는 화면의 크기가 바뀌거나, Component가 추가 되거나 제거 되었을 경우에 호출 됩니다.(이경우 즉시 다시 배치하지 않으며 Layout을 다시 그릴 필요가 있다는것을 표시한 후 validate함수가 호출되거나 화면이 다시 그려지는 경우에 다시 배치 작업을 수행 합니다. 따라서 Layout Manager를 설치후 즉시 효과를 볼려면 validate를 호출해야 합니다. Invalidate 함수는 특정 Component가 화면에 다시 배치해야 된다고 표시하는 것 입니다.
Layout Manager를 이용하는 경우에 수동으로 Component를 배치하는것이 소용 없습니다. 화면에 표시 될때 Layout Manager가 다시 위치, 크기등을 결정하기 때문 입니다. 수동으로 Layout을 설정하는 경우엔 위치, 크기등을 정해 주어야 하며 그렇지 않은 경우엔 초기 위치, 쿠기등이 정해지지 않으며 보통 화면에 나타나지 않습니다.
Layout Manager를 이용할 경우 크기지정이 유효한 경우는 Window, Frame등과 같은 최상위 Container 입니다.
수동으로 Component 배치하기
주로 소량의 정보를 보이거나 간단한 사용자 입력을 받는 Container에 사용 됩니다.
컨테이너에 설정해야 하는것들…
- 컨테이너의 크기를 고정 시킵니다.(Frame의 경우 setResizable)
- 컨테이너의 Layout Manager를 null로 한다. setLatout을 이용하며 Frame, Panel과 같은 기본 Layout Manager를 가지기 때문에 반드시 이과정을 수행해야 합니다.
- 컨테이너의 크기를 지정 합니다. (자식 컴포넌트의 크기, 위치를 수동으로 주는 경우 상의 컨테이너의 크기도 수동으로 지정해야 합니다. setSize, setBounds 등이용)
[예제]
import java.awt.*;
public class LayoutNull {
public static void main(String[] args) {
Button btn1, btn2, btn3;
Frame myWindow = new Frame("Null Layout");
myWindow.setResizable(false);
myWindow.setLayout(null);
myWindow.setSize(300, 300);
btn1 = new Button("버튼1"); btn1.setBounds(40,50,50,20);
btn2 = new Button("버튼2"); btn2.setBounds(100,50,50,20);
btn3 = new Button("버튼3"); btn3.setBounds(160,50,50,20);
myWindow.add(btn1); myWindow.add(btn2); myWindow.add(btn3);
myWindow.setVisible(true);
}
}
[결과]
인터페이스 java.awt.LayoutManager
컨테이너를 배치하는 클래스의 인터페이스를 정의 합니다.
addLayoutComponent(String, Component) : 지정된 이름을 가진 지정된 컴포넌트를 배치에 추가
layoutContainer(Container) : 지정된 패널에 컨테이너를 배치
minimumLayoutSize(Container) : 지정된 상위 컨테이너에서 컴포넌트를 받은 지정된 패널의 최소 크기를 계산
preferredLayoutSize(Container) : 지정된 상위 컨테이너에서 컴포넌트를 받은 지정된 패널의 환경설정된 크기를 계산
removeLayoutComponent(Component) : 배치에서 지정된 컴포넌트를 제거
LayoutManager2를 구현하는 java.awt의 클래스 - BorderLayout, CardLayout, GridBagLayout, GridLayout, FlowLayout
인터페이스 java.awt.LayoutManager2
LayoutManager2 인터페이스는 LayoutManager 인터페이스를 확장하여 배치에 컴포넌트를 추가하는 방식 및 위치를 지정하는 제약 조건 객체에 따라 배치를 명시적으로 처리 합니다.
addLayoutComponent(Component, Object) : 지정된 제약 조건 객체를 사용하여 지정된 컴포넌트를 배치에 추가 합니다.
getLayoutAlignmentX(Container) : x 축 정렬을 리턴 합니다.
getLayoutAlignmentY(Container) : y 축 정렬을 리턴 합니다.
invalidateLayout(Container) : 배치 관리 프로그램이 버려야 할 정보를 캐시에 넣은 경우 그 사실을 나타내고 배치를 무효화 합니다.
maximumLayoutSize(Container) : 컴포넌트의 최대 크기를 리턴 합니다.
LayoutManager2를 구현하는 java.awt의 클래스 - BorderLayout, CardLayout, GridBagLayout
FlowLayout
컴포넌트를 컨테이너에 연속된 행으로 위치 시킨다. 각 행에 많은 컴포넌트를 채우고 행이 다차면 다음으로 넘어간다. 주로 버튼등을 배열하기 위한 것
컴포넘트의 기본 위치는 행의 한가운데 입니다.
다음과 같은 행의 기본위치를 지정할수 있는 상수가 있습니다.
FlowLayout.LEFT, FlowLayout.RIGHT, FlowLayout.CENTER,
[예제]
import java.awt.*;
class FlowLayoutTest extends Frame {
public FlowLayoutTest() {
setLayout(new FlowLayout());
add(new Button("Button1"));
add(new Button("Button2"));
add(new MyButton("새로운 버튼"));
Panel p = new Panel();
p.add(new Button("Panel Button1"));
p.add(new Button("Panel Button2"));
add(p);
}
public static void main(String[] args) {
Frame f1 = new FlowLayoutTest();
f1.setTitle("Flow Layout Test : default");
f1.setBounds(0, 0, 200, 300);
f1.setVisible(true);
Frame f2 = new FlowLayoutTest();
//((FlowLayout)f2.getLayout()).setAlignment(FlowLayout.LEFT);
FlowLayout flow = new FlowLayout(FlowLayout.LEFT);
flow.setVgap(50);
f2.setLayout(flow);
f2.setTitle("Flow Layout Test : left");
f2.setBounds(200, 0, 200, 300);
f2.setVisible(true);
}
}
class MyButton extends Button {
public MyButton(String text) {
super(text);
}
public Dimension getPreferredSize() {
return new Dimension(super.getPreferredSize().width+30, super.getPreferredSize().height+30);
}
}
GridLayout
각 격자끼리의 width, height는 동일 합니다.
GridLay() : 행이 하나인 GridLayout을 만듭니다.
GridLayout(int row, int col) : 주어진 행과 열의 GridLayout을 만듭니다.
GridLayout(int row, int col, int hgap, int vgap)
[예제]
import java.awt.*;
class GridLayoutTest extends Frame {
public GridLayoutTest(String t, LayoutManager m, int x, int y) {
setTitle("GridLAyout Test " + t);
setLayout(m);
add(new Button("Button1"));
add(new Button("Button2"));
add(new Button("Button3"));
add(new Button("Button4"));
add(new Button("Button5"));
add(new Button("Button6"));
add(new Button("Button7"));
setBounds(x, y, 300, 300);
setVisible(true);
}
public static void main(String[] args) {
new GridLayoutTest("디폴트", new GridLayout(), 0, 0);
new GridLayoutTest("2, 0", new GridLayout(2, 0), 300, 0);
new GridLayoutTest("0, 2", new GridLayout(0, 2), 0, 300);
new GridLayoutTest("3, 3", new GridLayout(3, 3), 300, 300);
}
}
GridBagLayout
Layout Manager중에서 가장 복잡하며, 보통 하나의 GridBagLayout을 사용하여 모든 종류의 폼을 구성할 수 있습니다.
융통성있는 배치 관리 프로그램으로 동일 크기의 컴포넌트를 요구하지 않으면서 컴포넌트를 수직 및 수평으로 정렬 합니다.
각 컴포넌트가 하나 이상의 셀을 차지하는 표시 영역이라 부르는 셀의 사각형 격자를 동적으로 유지 관리 합니다.
GridBagLayout으로 관리하는 각 컴포넌트는 표시 영역에서 컴포넌트 배치 방식을 지정하는 GridBagConstraints의 인스턴와 관련 됩니다
GridBagLayout을 효율적으로 사용하려면 해당 컴포넌트와 관련된 GridBagConstraints 객체를 하나 이상 조정해야 합니다. 그렇게 함으로서 컴포넌트를 원하는 크기와 위치로 배치합니다.
실제 GridBagLayout을 사용하는것 보다 여러 개의 컨테이너와 Layout Manager를 계층적으로 사용하는것이 훨씬 효율적 입니다.
GridBagConstraints
- gridx, gridy : 해당 컴포넌트가 들어가게될 격자의 x번째, y번째 값, 가장 왼쪽 셀의 주소는 gridx=0, gridy=0 입니다.
- gridwidth, gridheight : 해당 열에 존재할수 있는 최대 컴포넌트의 개수, int값 사용, GridBagConstraints.RELATIVE는 컴포넌트들이 이어져서 들어갈수 있게 해주며,GridBagConstraints.REMAINDER는 마지막 자리에 위치해서 더 이상 컴포넌트가 들어갈수 없게 합니다.
- fill : 컴포넌트를 채울때 특정 방향으로 컴포넌트를 늘여 격자를 채울수 있게 합니다. GridBagConstraints.BOTH, GridBagConstraints.HORIZONTAL, GridBagConstraints.VERTICAL등이 있다.
- ipadx, ipady : 컴포넌트가 가지는 내부적 간격, int값 사용 합니다.
- insets : 컴포넌트와 격자와의 외부적인 간격, java.awt.inset 객체가 사용 됩니다.
- anchor : 격자내에서 컴포넌트가 위치하게 되는 격자내의 절대적인 위치, GridBagConstraints.CENTER(기본값), GridBagConstraints.NORTH, GridBagConstraints.NORTHEAST, GridBagConstraints.EAST, GridBagConstraints.SOUTHEAST, GridBagConstraints.SOUTH, GridBagConstraints.SOUTHWEST, GridBagConstraints.NORTHWEST등이 있습니다.
- weightx, weighty : 컴포넌트가 차지할수 있는 가로와 세로의 영역비율, double 값이 사용 됩니다.
[예제]
import java.awt.*;
public class GridBagLayoutTest extends Frame{
public GridBagLayoutTest(String t) {
super(t);
GridBagLayout gbag = new GridBagLayout();
GridBagConstraints con = new GridBagConstraints();
setLayout(gbag);
con.fill=GridBagConstraints.BOTH;
add(new Button("버튼1"), con);
add(new Button("버튼2"), con);
con.gridwidth = GridBagConstraints.REMAINDER;
add(new Button("버튼3"), con);
add(new Button("버튼4"), con);
con.gridwidth = GridBagConstraints.RELATIVE;
add(new Button("버튼5"), con);
con.gridwidth = GridBagConstraints.REMAINDER;
add(new Button("버튼6"), con);
con.gridwidth = 1;
con.gridheight = 2;
add(new Button("버튼7"), con);
con.gridwidth = GridBagConstraints.REMAINDER;
con.gridheight = 1;
add(new Button("버튼8"), con);
add(new Button("버튼9"), con);
}
public static void main(String[] args) {
Frame f = new GridBagLayoutTest("GridBagLayout");
f.setSize(300, 200);
f.setVisible(true);
}
}
CardLayout
여러화면을 겹쳐 두었다가 특정한 화면만 보이도록 할 경우 사용 합니다.
여러 장의 카드가 있으나 보이는 카드는 하나만 있다는 개념에서 나온 이름 입니다
first(), last(), next(), previous() 등의 도구를 사용하여 카드 간에 순차적으로 이동할 수도 있습니다.
CardLayout() : 간격 크기가 제로(0)인 새로운 카드를 작성 합니다.
CardLayout(int, int) : 지정된 수평 간격 및 수직 간격으로 새로운 카드 배치를 작성 합니다.
[예제] //닫기 기능 추가
import java.awt.*;
import java.awt.event.*;
public class CardLayoutTest1 extends Frame {
public static void main(String[] args) {
Frame f = new Frame("CardLayoutTest");
final Panel tabs = new Panel();
tabs.add(new Button("<><"));>
tabs.add(new Button("<"));
tabs.add(new Button("Options"));
tabs.add(new Button("Settings"));
tabs.add(new Button("Preferences"));
tabs.add(new Button(">"));
tabs.add(new Button(">>"));
f.add(tabs, "North");
final CardLayout layout = new CardLayout();
final Panel cards = new Panel(layout);
cards.add(new CardPanel("Options"), "Options");
cards.add(new CardPanel("Settings"), "Settings");
cards.add(new CardPanel("Preferences"), "Preferences");
f.add(cards, "Center");
ActionListener al = new ActionListener() {
public void actionPerformed(ActionEvent ev) {
String cmd = ev.getActionCommand();
if (cmd.equals("<><")) layout.first(cards);
else if (cmd.equals("<")) layout.previous(cards);>
else if (cmd.equals(">")) layout.next(cards);
else if (cmd.equals(">>")) layout.last(cards);
else layout.show(cards, cmd);
}
};
for(int i=0; i
((Button)tabs.getComponent(i)).addActionListener(al);
}
f.setSize(400, 300);
f.setVisible(true);
f.addWindowListener(new WindowListenerProcessing() );
}
}
class CardPanel extends Panel {
CardPanel(String name) {
setLayout(new BorderLayout());
add(new Label("CardPanel : " + name, Label.CENTER),"Center");
Panel p = new Panel();
add(p, "South");
Button btn = new Button("Close");
ActionListener a1 = new ActionListener() {
public void actionPerformed(ActionEvent ev) {
String cmd = ev.getActionCommand();
if (cmd.equals("Close")) {
System.exit(0);
}
}
};
btn.addActionListener(a1);
p.add(btn);
}
}
class WindowListenerProcessing extends WindowAdapter {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
댓글 없음:
댓글 쓰기