컨테이너와 배치
u 컨테이너의 이해
Ø 컨테이너는 자신의 영역 안에 다른 컴포넌트를 포함할 수 있는 컴포넌트를 의미한다.
Ø 컨테이너는 그 자신만으로는 특별한 동작을 할 수 없고, 다른 컴포넌트를 포함할 때만 의미가 있다. 컨테이너 그 자체도 컴포넌트로 취급되며 다른 컨테이너에 부탁될 수 있다.
Ø Panel : 다른 컨테이너에 부착되어 일부 영역을 컨트롤 하는데 많이 사용된다.
Ø Dialog : 대화창에서 주로 사용되는 컨테이너이다.
Ø Applet 과 Frame 은 대표적인 최상위 컨테이너로써 다른 컨테이너를 포함한 맨 바깥쪽 컨테이너를 의미한다.
u 컨테이너의 사용
컨테이너 |
설명 | ||||||||||
Window 컨테이너 |
최상위 윈도우를 제공하는 컨테이너, Frame Dialog 컨테이너가 주로 대신 사용됨
| ||||||||||
Frame 컨테이너 |
다른 컨테이너와 마찬가지로 add() 메소드를 사용. 배치 요구. Frame 클래스 생성 후 setSize() 또는 setBounds() 메소드를 이용해서 크기를 꼭 정해줘야 하며 하부 컴포넌트 배치를 위해 pack() 메소드를 호출하고 마지막으로 setVisible(true) 메소드를 통해 화면에 표시해야 한다. 코드 및 예는 표 하부를 참조할 것 | ||||||||||
Panel 컨테이너 |
Applet과 Frame 클래스가 가장 바깥쪽의 컨테이너 역할을 하는데 반해, Panel 클래스는 컴포넌트들을 그룹별로 모을 때 주로 사용한다. 보통 GUI를 설계할 때 컴포넌트를 독립적으로 Applet과 Frame에 바로 붙이기 보다는 Panel 클래스에 그룹별로 붙이고 패널 클래스들을 배치하는 경우가 대부분이다. 코드 및 예는 표 하부를 참조할 것 | ||||||||||
Applet 컨테이너 |
Applet 클래스는 16장에서 살펴본다. setSize(), setBounds() 메소드를 해 주어도 원하는 크기대로 웹 브라우저에서 나타나지 않는 경우가 있다. 왜냐면 브라우저의 종류에 따라서 조금씩 차이가 있기 때문에 직접적인 메소드보다는 HTML 태그의 사이즈 부분에 값을 주는 것이 바람직하다. | ||||||||||
Dialog 컨테이너 |
팝업 윈도우의 형태로 메인 윈도우 외에 따로 메시지를 출력하거나, 사용자의 입력을 받을 때 주로 사용되는 컨테이너다. 생성자를 알아보자
생성과정 ① Dialog 클래스 상속 : 상속을 통해서 개발자가 새로운 대화창을 만든다. ② super() 를 이용하여 생성자 호출 ③ setVisible() 메소드 호출 코드 및 사용 예는 표 하부를 참조할 것 |
Ø Frame 컨테이너 사용 예
import java.awt.*; public class FrameTest { public static void main(String args[]){ Frame f = new Frame("테스트 프레임"); // 프레임 생성 Label l = new Label("5초 후에 없어지는 프레임"); f.add(l); f.setBounds(10, 10, 300, 200); //크기 위치 셋팅 f.setVisible(true); // 화면에 나타낸다. try{ Thread.sleep(5*1000); }catch(InterruptedException e) f.setVisible(false); f.dispose(); // 자원을 해제한다. } } |
<실행결과> |
Ø Panel 컨테이너 사용 예
import java.awt.*; import java.awt.event.*; import java.applet.*; public class PanelTest extends Applet implements ActionListener{ Panel panel1, panel2; Button button1, button2, button3, button4; public void init(){ panel1 = new Panel(); panel2 = new Panel(); panel1.setBackground(Color.red); panel2.setBackground(Color.yellow); add(panel1); add(panel2); button1 = new Button("패널 2 보이기"); button2 = new Button("패널 2 안보이기"); button3 = new Button("패널 1 보이기"); button4 = new Button("패널 1 안보이기"); button1.addActionListener(this); button2.addActionListener(this); button3.addActionListener(this); button4.addActionListener(this); panel1.add(button1); panel1.add(button2); panel2.add(button3); panel2.add(button4); } // 버튼이 눌리면 actionPerformed() 메소드가 호출된다. public void actionPerformed(ActionEvent ae){ Button b = (Button)ae.getSource(); String label = b.getLabel(); if(label.equals("패널 1 보이기")) panel1.setVisible(true); else if(label.equals("패널 1 안보이기")) panel1.setVisible(false); else if(label.equals("패널 2 보이기")) panel2.setVisible(true); else panel2.setVisible(false); } } |
<실행결과> |
Ø Dialog 컨테이너 사용 예
<Notification.java> import java.awt.*; import java.awt.event.*; class Notification extends Dialog implements ActionListener{ String msg; public Notification(Frame f, String s){ super(f,"주목",true); msg = s; } public void disp(){ Button b; add("North", new Label(msg,Label.CENTER)); b = new Button("OK"); b.addActionListener(this); Panel p = new Panel(); p.add(b); add("South", p); setBackground(Color.gray); setSize(160,100); setVisible(true); } public void actionPerformed(ActionEvent e){ dispose(); } } <TestDialog.java> import java.awt.*; import java.awt.event.*; class TestDialog extends Frame implements ActionListener{ Notification n; public TestDialog(){ super("다이얼로그를 테스트합니다."); n = new Notification(this,"다이얼로그가 보입니다"); Panel p = new Panel(); Button b1 = new Button("다이얼로그 열기"); b1.addActionListener(this); p.add(b1); add(p); setSize(300,150); setVisible(true); } public void actionPerformed(ActionEvent e){ n.disp(); } public static void main(String args[]){ TestDialog t = new TestDialog(); } } |
<실행결과> |
u 배치에 대한 이해
Ø 문제 분석 : GUI에서 화면을 구성하기 위해서는 컴포넌트의 위치를 좌표로 지정해 주었다. 다른 운용체제에서 절대 좌표를 입력하면 다르게 표시되어 원하는 모습이 나오지 않는다. 또한 컨테이너의 사이즈를 재조정하면 그 안에 들어 있는 컴포넌트의 위치가 제각각 변하기 때문에 배치 개념이 나옴
Ø 문제 해결 : 플랫폼 독립성의 특징을 이용해 컴포넌트의 배치를 배치 관리자(Layout Manager)라는 것을 이용하여 처리하도록 한다. 배치 관리자는 LayoutManager 인터페이스를 반드시 구현하도록 되어 있는데 이 배치 관리자를 통해 컴포넌트를 영역에 배치한다.
Ø 컨테이너가 배치 관리자에게 컴포넌트를 배치하는 것을 요청하면 컴포넌트 간의 간격이나 컴포넌트의 크기 등의 윈도우 시스템에 종속적인 값을 배치 관리자가 하위 윈도우 시스템에 가장 적합한 값으로 매핑해서 화면에 보여준다.
Ø 디폴트 배치 관리자
컨테이너 |
배치 관리자 |
Applet, Panel |
FlowLayout |
Window, Frame, Dialog |
BorderLayout |
Ø 자바의 컨테이너가 배치 관리자를 사용하기 위한 절차
① 필요한 배치를 지원하는 배치 관리자 클래스 객체를 생성 ② 배치 관리자 클래스를 컴포넌트의 setLayout() 메소드를 이용하여 컨테이너에 설정 ③ 이후 add() 메소드로 추가되는 컴포넌트는 설정된 배치 관리자 클래스에 |
u Flow 레이아웃
Ø 컨테이너에 주어진 컴포넌트를 왼쪽에서 오른쪽으로, 위에서 아래쪽으로 순차적으로 쭉 배열한다.
Ø 배치시 주의점은 컴포넌트가 지정한 크기를 무시하고 각 컴포넌트에 필요한 최소한의 높이와 위치, 간격이 자동적으로 지정되어 배치된다.
Ø 코드는 생략하고 실행결과와 특징변화의 예시를 보자.
<실행결과> (기본모습) (옆으로 윈도우를 늘렸을 때) |
u Border 레이아웃
Ø 각 배치에는 “North”, “East”, “South”, “West”, “Center”의 이름이 붙어 있다.
Ø 각 이름은 컴포넌트를 컨테이너에 포함시킬 때, 같이 주어지며 이에 의해서 컴포넌트가 포함되는 위치가 정해진다.
Ø 소스 코드 및 실행 결과
import java.awt.*; public class BorderTest extends Frame{ public static void main(String args[]){ BorderTest f = new BorderTest(); f.setLayout(new BorderLayout()); f.add("North", new Button("첫번째")); f.add("East", new Button("두번째")); f.add("West", new Button("세번째")); f.add("South", new Button("네번째")); f.add("Center", new Button("다섯번째")); f.setSize(300,300); f.setVisible(true); } } |
<실행결과> |
u Grid 레이아웃
Ø 그리드 레이아웃은 생성할 때 컬럼수와 라인수를 지정한다.
Ø 레이아웃에서는 배치되는 컴포넌트의 크기와 상관없이 각 셀의 크기와 고정적이기 때문에 컴포넌트의 사이즈가 완전히 무시된다. 컴포넌트를 추가하면 좌측에서 우측으로, 상단에서 하단의 순서대로 컴포넌트가 추가된다.
Ø 소스 코드 및 실행 결과
import java.awt.*; public class GridTest extends Frame{ public static void main(String args[]){ GridTest f = new GridTest(); f.setLayout(new GridLayout(3,2)); f.add("North", new Button("첫번째")); f.add("East", new Button("두번째")); f.add("West", new Button("세번째")); f.add("South", new Button("네번째")); f.add("Center", new Button("다섯번째")); f.setSize(300,300); f.setVisible(true); } } |
<실행결과> |
u Card 레이아웃
Ø 카드를 포개어 놓은 듯한 레이아웃 형태로서 포개 놓으면 맨 위의 카드밖에는 볼 수 없듯이 이 배치 관리자를 쓰면 한번에 하나의 컴포넌트밖에는 볼 수 없다.
Ø 소스 코드 및 실행결과
import java.awt.*; import java.awt.event.*; public class CardTest extends Frame implements ActionListener{ CardLayout cl; public static void main(String args[]){ CardTest f = new CardTest(); Button b; f.cl = new CardLayout(); f.setLayout(f.cl); b = new Button("첫번째"); b.addActionListener(f); f.add("1,", b); b = new Button("두번째"); b.addActionListener(f); f.add("2,", b); b = new Button("세번째"); b.addActionListener(f); f.add("3,", b); b = new Button("네번째"); b.addActionListener(f); f.add("4,", b); b = new Button("다섯번째"); b.addActionListener(f); f.add("5,", b); f.setSize(300,300); f.setVisible(true); } public void actionPerformed(ActionEvent e){ cl.next(this); } } |
<실행결과> (첫 화면) (첫 화면 클릭 후 두번째 화면) |
u GridBag 레이아웃
Ø 지정된 사이즈를 좌표를 이용해 영역 구분을 해준다.
Ø 소스 코드 및 실행 결과
import java.awt.*; import java.util.*; public class GridBagTest extends Panel{ GridBagConstraints c; public GridBagTest(){ GridBagLayout gridbag = new GridBagLayout(); setLayout(gridbag); setBackground(Color.red); c = new GridBagConstraints(); c.weightx = 1.0; c.weighty = 1.0; c.fill = GridBagConstraints.BOTH; layout(new Button("첫번째"), 0,0,1,2); layout(new Button("두번째"), 2,0,2,1); layout(new Button("세번째"), 1,1,1,1); layout(new Button("네번째"), 2,1,1,1); } public void layout(Component obj, int x, int y, int width, int height){ c.gridx = x; c.gridy = y; c.gridwidth = width; c.gridheight = height; add(obj, c); } public static void main(String args[]){ Frame test = new Frame(); test.setSize(300,300); test.add(new GridBagTest()); test.setVisible(true); } } |
<실행결과> |