[Day +27]GUI / Java Swing, 컨테이너, 컴포넌트
210729 목
GUI(Graphic User Interface)
<-> CLI(Command Line Interface)
-대부분의 소프트웨어 환경은 GUI이다.
*GUI의 중요도는 낮은 편이다. 프로젝트 구현 정도의 실력을 가지면 된다.
1. GUI 특징
1) AWT
-AWT 패키지 하위에 클래스들이 많음
-윈도우의 OS컴포넌트를 그대로 사용하는 것이 특징
2) Swing
: AWT를 확장한 GUI프로그래밍 도구
-클래스명 앞에 J를 붙여서 AWT와 구분
예) JButton, JPannel
3) 컨테이너
-가장 바깥에 있는 GUI 컴포넌트
-컨테이너가 존재해야 다른 컴포넌트들을 올릴 수 있다
4) 컴포넌트
-컨테이너에 포함되어야 화면에 출력될 수 있는 GUI 객체
-Java.awt.Component 클래스는 모든 GUI컴포넌트의 최상위 클래스
-스윙컴포넌트의 최상위 클래스는 javax.swing.Jcomponent
<컨테이너와 컴포넌트의 포함관계>

2. 작업 순서
1) 컨테이너 객체 생성
-JFrame 상속 이용
2) 컨테이너에 레이아웃 설정
3) 컴포넌트 객체 생성
4) 지정된 배치 방식에 따라 컨테이너에 컴포넌트 배치
5) 컴포넌트에 마우스나 키보드 반응에 대한 이벤트 처리함
<컨테이너 배치 방식 지정>
1) BorderLayOut
-모두 5개 영역으로 나누고, 각 영역에 하나의 컴포넌트를 넣을 수 있음
-한 영역에 하나 이상의 컴포넌트를 넣고 싶으면 Panel을 사용
2) FlowLayout
-컴포넌트를 워드프로세서와 같은 방식, 즉 왼쪽에서 오른쪽으로 배치
-3가지 정렬 방식(왼쪽, 가운데, 오른쪽)이 가능
3) GridLayout
-컴포넌트들을 가로, 세로의 일정 수만큼 배치하고자 할 때 주로 사용
-행과 열을 지정하고, 각 컴포넌트는 동일한 사이즈를 가짐
4) CardLayout
-여러 컨테이너를 슬라이드처럼 바꿔가며 보여줄 수 있음
-앨범이나 퀴즈 또는 설치 프로그램에 주로 사용
5) NullLayout
-레이아웃 지정 없이 위치를 지정하여 배치하는 방법
-컴포넌트의 위치와 크기를 자유롭게 만들 수 있음
기본
1-1> JFrameView1
package com.kh.chap01_container.view;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
//JFrame생성하기1
//javax.swing.JFrame 클래스를 상속 받아 생성자에서 프레임에 대해 설정
public class JFrameView1 extends JFrame {
//기본 생성자 안에 프레임 기본 세팅 설정하기
public JFrameView1() {
//프레임 위치 설정(x, y) => 픽셀 기준
this.setLocation(300, 200);
//프레임 크기 설정(width, height)
this.setSize(800, 500);
//프레임 위치와 크기 한번에 설정(x, y, width, height)
this.setBounds(300, 200, 800, 500);
//프레임 상단에 이름 설정
this.setTitle("My Boo");
//프레임 상단에 로고 이미지 변경
try {
this.setIconImage(ImageIO.read(new File("image/icon.png")));
} catch (IOException e) {
e.printStackTrace();
}
//기본 값으로 프레임 사이즈 조정이 활성화되어 있으므로 사이즈를 임의로 조정할 수 없게 설정
this.setResizable(false);
//창에서 X버튼을 눌러서 종료를 해도 프로세스는 계속 실행 중
//닫기 버튼을 눌렀을 때 프로세스 정상 종료를 위한 구문 추가
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//화면이 보여지게 만들기 위해서는 반드시 setVisible(true) 호출 필요
//프레임 위에 올라간 컴포넌트들이 잘 보이려면 마지막에 호출
this.setVisible(true);
//=> 이 두 메소드는 꼭 넣는다고 생각하자! 而且 setVisible을 마지막에 넣는다고 생각하자!
}
}
1-2> JFrameView2
package com.kh.chap01_container.view;
import java.awt.Rectangle;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
//JFrame 생성하기2
//javax.swing.JFrame 클래스를 객체로 생성 후
//해당 프레임 객체의 설정 값을 변경하는 방법
public class JFrameView2 {
public void showJFrame() {
// JFrame mainFrame = new JFrame();
// mainFrame.setTitle("My Boo");
//매개변수 생성자로 title 전달하면서 JFrame 객체 생성
JFrame mainFrame = new JFrame("My Boo");
//위치와 사이즈 설정 => 객체를 먼저 만들어주는 방법도 있음
//Rectangle 객체를 활용(x, y, width, height)
Rectangle r = new Rectangle(300, 200, 800, 500);
mainFrame.setBounds(r);
//사이즈 변경 불가
mainFrame.setResizable(false);
//아이콘 이미지 변경
try {
mainFrame.setIconImage(ImageIO.read(new File("image/icon.png")));
} catch (IOException e) {
e.printStackTrace();
}
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.setVisible(true);
}
}
답) 1, 2번 답 동일

package com.kh.chap01_container.run;
import com.kh.chap01_container.view.JFrameView1;
import com.kh.chap01_container.view.JFrameView2;
public class Run {
public static void main(String[] args) {
//JFrameView1 jf = new JFrameView1();
JFrameView2 jf = new JFrameView2();
jf.showJFrame();
}
}
레이아웃
2-1> BorderLayout
package com.kh.chap02_layout.view;
import java.awt.BorderLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
public class A_BorderLayout extends JFrame {
public A_BorderLayout() {
//부모 생성자로 JFrame title 전달
super("BorderLayout");
//프레임 위치 및 크기 설정
this.setBounds(300, 200, 800, 500);
//레이아웃 설정하기
//LayoutManager 인터페이스의 후손 클래스로 다양한 레이아웃이 제공됨
this.setLayout(new BorderLayout(10, 10));
//=>주석처리를 해도 같은 값이 나옴.
//현재 적용 된 레이아웃 알아보기
//=> 미설정 시 JFrame의 기본 레이아웃도 BorderLayout임
System.out.println(this.getLayout());
//답 : java.awt.BorderLayout[hgap=0,vgap=0]
//JButton 객체 생성 => 객체 생성만으로 화면에 표현되는 것이 아님
JButton north = new JButton("북");
JButton south = new JButton("남");
JButton east = new JButton("동");
JButton west = new JButton("서");
JButton center = new JButton("중간");
//화면에 추가하기 위해서 add 메소드로 jframe 위에 jbutton 추가
//위치 지정 문자열 틀렸을 경우 오류 발생 유의
this.add(north, "North");
this.add(south, "South");
this.add(east, "East");
this.add(west, "West");
this.add(center, "Center");
//반드시 필요한 코드
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
}
답)

2-2> FlowLayout
package com.kh.chap02_layout.view;
import java.awt.FlowLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
public class B_FlowLayout extends JFrame {
public B_FlowLayout() {
super("FlowLayout");
this.setBounds(300, 200, 800, 500);
//FlowLayout 설정
//컴포넌트들을 가로나 세로 방향의 줄 단위로 배치하는 레이아웃
//만약 컨테이너보다 배치할 구성 요소가 더 많거나 크게 되면 자동으로 다음 줄로 넘기며 배치
this.setLayout(new FlowLayout()); //기본 정렬 설정은 Center
//정렬 기준 전달
this.setLayout(new FlowLayout(FlowLayout.CENTER));
this.setLayout(new FlowLayout(FlowLayout.LEFT));
this.setLayout(new FlowLayout(FlowLayout.RIGHT));
for(int i = 0 ; i < 15 ; i++) {
this.add(new JButton(i+1+"번"));
}
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
}
답)

2-3> GridLayout
package com.kh.chap02_layout.view;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
public class C_GridLayout extends JFrame {
public C_GridLayout() {
super("GridLayout");
this.setBounds(300, 200, 800, 500);
//GridLayout
//컴포넌트들을 가로, 세로의 일정 수만큼 배치하고자 할 때 사용
//윗 줄부터 시작해서 왼쪽에서오른쪽으로 움직이며 각 줄을 이동하며 컴포넌트 배치
//생성자(가로칸, 세로칸, 가로갭, 세로갭)
this.setLayout(new GridLayout(0, 5, 10, 20));
// => 컴포넌트 개수가 맞지 않으면 rows에 설정된 값이 우선 된다.(가로값 우선)
// => 만약 cols를 우선시 하고 싶은 경우 row는 0으로 두면 된다.
for(int i = 1 ; i <= 40 ; i++) {
this.add(new JButton(i + "번"));
}
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
}
답)

2-4> CardLayout
package com.kh.chap02_layout.view;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class D_CardLayout extends JFrame{
public D_CardLayout() {
super("CardLayout");
this.setBounds(300, 200, 800, 500);
//CardLayout
//Panel을 이용해서 카드판을 만들어 겹쳐놓음
//이벤트를 이용해서 다른 판이 보이게 설정해야 함
CardLayout card = new CardLayout();
this.setLayout(card);
//패널 생성
//패널은 컴포넌트지만 다른 컴포넌트를 포함할 수 있는 컨테이너의 성격을 지님
JPanel card1 = new JPanel();
JPanel card2 = new JPanel();
JPanel card3 = new JPanel();
//패널마다 배경색 지정하기
card1.setBackground(Color.GRAY);
card2.setBackground(Color.YELLOW);
card3.setBackground(new Color(50,100, 100));
//패널에 라벨 추가
card1.add(new JLabel("Card1"));
card2.add(new JLabel("Card2"));
card3.add(new JLabel("Card3"));
//메인 프레임에 패널 추가
this.add(card1);
this.add(card2);
this.add(card3);
//패널에 이벤트 추가
card1.addMouseListener(new MouseAdapter() {
//card1 패널에 마우스 클릭 이벤트가 일어날 때 수행할 코드 작성
@Override
public void mouseClicked(MouseEvent e) {
//왼쪽 버튼1, 휠 2, 오른쪽 버튼3
System.out.println(e.getButton());
//감지 될때 1, 2, 3의 숫자가 콘솔창에 뜬다
//왼쪽 버튼이 클릭 되었을 때 카드 레이아웃을 다음 카드로 변경
if(e.getButton() == MouseEvent.BUTTON1) {
card.next(card1.getParent());
//오른쪽 버튼이 클릭 되었을 때 카드 레이아웃의 이전 카드로 변경
}else if(e.getButton() == MouseEvent.BUTTON3) {
card.previous(card1.getParent());
}
}
});
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
}
답)

2-5> NullLayout
package com.kh.chap02_layout.view;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
public class E_NullLayout extends JFrame {
public E_NullLayout() {
super("NullLayout");
this.setBounds(200, 200, 500, 500);
//Layout 지정 없이 위치 지정하면서 배치하는 방법
this.setLayout(null);
JLabel lb = new JLabel("이 름 : ");
lb.setLocation(50, 100);
lb.setSize(150,50);
JTextField tf = new JTextField(20);
tf.setLocation(110, 100);
tf.setSize(200,50);
JButton btn = new JButton("추 가");
btn.setLocation(350, 100);
btn.setSize(100,50);
//프레임에 생성된 컴포넌트 추가
//Layout이 null인 상태에서 컴포넌트의 위치 설정이 없으면
//프레임에 올라갈 수 없다
this.add(lb);
this.add(tf);
this.add(btn);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
}
답)

package com.kh.chap02_layout.view;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class F_PanelLayout extends JFrame {
public F_PanelLayout() {
super("PanelLayout");
this.setBounds(200, 200, 500, 500);
//컴포넌트 생성
JLabel lb = new JLabel("이 름 : ");
lb.setLocation(50, 100);
lb.setSize(150,50);
JTextField tf = new JTextField(20);
tf.setLocation(110, 100);
tf.setSize(200,50);
JButton btn = new JButton("추 가");
btn.setLocation(350, 100);
btn.setSize(100,50);
//JPanel 생성
JPanel panel = new JPanel();
//Panel의 레이아웃 기본 값은 FlowLayout(정렬은 Center / B참조하세요)
//패널에 위치를 정해서 컴포넌트를 올리고 싶다면 패널의 레이아웃을 null로 변경
panel.setLayout(null);
//패널에 컴포넌트 생성
panel.add(lb);
panel.add(tf);
panel.add(btn);
//패널을 프레임에 추가
this.add(panel);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
}
답)

package com.kh.chap02_layout.run;
import com.kh.chap02_layout.view.A_BorderLayout;
import com.kh.chap02_layout.view.B_FlowLayout;
import com.kh.chap02_layout.view.C_GridLayout;
import com.kh.chap02_layout.view.D_CardLayout;
import com.kh.chap02_layout.view.E_NullLayout;
import com.kh.chap02_layout.view.F_PanelLayout;
public class Run {
public static void main(String[] args) {
A_BorderLayout a = new A_BorderLayout();
//B_FlowLayout b = new B_FlowLayout();
//C_GridLayout c = new C_GridLayout();
//D_CardLayout d = new D_CardLayout();
//E_NullLayout e = new E_NullLayout();
//F_PanelLayout f = new F_PanelLayout();
}
}
Component
3-1> TextField
package com.kh.chap03_component.view;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class A_TextField {
public void testFieldTest() {
JFrame frame = new JFrame("제곱 계산하기");
frame.setSize(300, 140);
//패널 생성
JPanel panel = new JPanel();
//라벨 패널에 부착
panel.add(new JLabel("숫자 입력 : "));
//텍스트 필드 생성
JTextField text = new JTextField(15);
panel.add(text);
//라벨 패널에 부착
panel.add(new JLabel("제곱한 값 : "));
//결과 텍스트 필드 생성
JTextField result = new JTextField(15);
//결과 텍스트 필드 수정 불가 설정
result.setEditable(false);
panel.add(result);
//버튼 생성
JButton btn = new JButton("OK");
panel.add(btn);
//버튼 클릭 시 발생하는 이벤트 감지
/*
* ActionEvent : 사용자가 어떤 동작을 할 때 발생하며 모든 컴포넌트에서 발생하지는 않음
* 1. 버튼이 눌러졌을 때
* 2. 메뉴를 클릭했을 때
* 3. 텍스트 필드에서 엔터키를 눌렀을 때
*/
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//클릭 시 text에 기록된 값 가져오기(문자열 파싱 처리)
int value = Integer.parseInt(text.getText());
//result에 제곱값 입력하기
result.setText(value*value + "");
//텍스트 상자로 다시 포커스 가져가기
text.requestFocus();
}});
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
답)

3-2> TextArea
package com.kh.chap03_component.view;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.JTextField;
public class B_TextArea {
public void textAreaTest() {
JFrame frame = new JFrame("textarea 테스트");
//입력용 텍스트 필드
JTextField tf = new JTextField(30);
//출력용 텍스트 필드
JTextArea ta = new JTextArea(10, 30);
//텍스트 필드에서 엔터키를 눌렀을 때 이벤트
tf.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//텍스트 필드에 입력 된 값 알아오기
String text = tf.getText();
//텍스트 영역에 setText가 아닌 append로 해당 값 추가하기
ta.append(text + "\n");
tf.setText("");
}});
frame.add(tf, "North");
frame.add(ta, "Center");
//프레임 크기를 지정하지 않으면 작게 나옴
//그래서 프레임의 크기를 컴포넌치 배치에 맞춰서 자동 설정하고 싶을 때
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
답)

3-3> RadioButton
package com.kh.chap03_component.view;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ButtonGroup;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
public class C_RadioButton {
public void radioButtonTest() {
JFrame frame = new JFrame("RadioButtonTest");
frame.setSize(300,150);
//상단 패널 생성
JPanel topPanel = new JPanel();
JLabel label = new JLabel("어떤 크기의 커피를 주문하시겠습니까?");
topPanel.add(label);
frame.add(topPanel, "North");
//중간 패널
JPanel sizePanel = new JPanel();
JRadioButton small = new JRadioButton("Small Size");
JRadioButton medium = new JRadioButton("Medium Size");
JRadioButton large = new JRadioButton("Large Size");
//버튼 그룹을 지정해주지 않으면 각자(모두 다) 선택 가능하게 동작한다.
//라디오 버튼은 복수 선택이 불가능한 선택을 받기 위한 컴포넌트이므로
//필수로 그룹으로 묶어줘야 한다
ButtonGroup sizeGroup = new ButtonGroup();
sizeGroup.add(small);
sizeGroup.add(medium);
sizeGroup.add(large);
sizePanel.add(small);
sizePanel.add(medium);
sizePanel.add(large);
frame.add(sizePanel, "Center");
//하단 패널
JPanel resultPanel = new JPanel();
JLabel text = new JLabel("크기가 선택되지 않았습니다");
resultPanel.add(text);
frame.add(resultPanel, "South");
//small size 버튼이 클릭되었을 때
small.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
text.setText("Small Size가 선택되었습니다");
}});
//medium size 버튼이 클릭되었을 때
medium.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
text.setText("Medium Size가 선택되었습니다");
}});
//large size 버튼이 클릭되었을 때
large.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
text.setText("Large Size가 선택되었습니다");
}});
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
답)

package com.kh.chap03_component.run;
import com.kh.chap03_component.view.A_TextField;
import com.kh.chap03_component.view.B_TextArea;
import com.kh.chap03_component.view.C_RadioButton;
public class Run {
public static void main(String[] args) {
A_TextField a = new A_TextField();
//a.testFieldTest();
B_TextArea b = new B_TextArea();
//b.textAreaTest();
C_RadioButton c = new C_RadioButton();
c.radioButtonTest();
}
}