티스토리 뷰

PL/JAVA

[JAVA] 자바 - GUI 기초(AWT와 스윙)

poopooreum 2024. 6. 11. 20:52
반응형

✏️ GUI 응용프로그램

GUIGraphical User Interface의 약자로 이미지 혹은 그래픽을 이용하여 메뉴 등을 포함하는 화면을 구성하고, 키보드 외 마우스 등의 편리한 입력 도구를 이용하여 사용자가 입력하기 편하도록 만들어진 사용자 인터페이스이다. 자바는 AWT와 Swing 패키지 등 강력한 GUI 라이브러리를 제공한다.

 

 

✏️ AWT와 Swing 패키지

자바 언어는 GUI 응용프로그램을 쉽게 작성할 수 있도록 다양한 GUI 컴포넌트(GUI Component)를 제공한다. 자바의 GUI 컴포넌트 AWT 컴포넌트 Swing 컴포넌트로 구분되며, 각각 java.awt 패키지java.swing 패키지를 통해 공급된다.

 

AWT

AWT(Abstract Windowing Toolkit)는 자바가 처음 나왔을 때 함께 배포된 패키지로, 많은 GUI 컴포넌트 (Frame,   Window, Panel, Dialog, Button, Label, TextFiled, Checkbox, Choice 등) 포함한다. 그리고 이 AWT 컴포넌트들 중량 컴포넌트(heavy weight component)로 불리는데, 이 컴포넌트들은 운영체제(native OS)의 도움을 받아 화면에 출력 되기 때문에 운영체제의 자원을 많이 소모하여 운영체제에 많은 부담을 준다. 그리고 응용프로그램의 GUI 모양이 운영 체제에 따라서 달라진다.

 

스윙(Swing)

스윙(Swing)AWT와 달리 순수 자바 언어로 작성되었고, 운영체제의 도움을 받지 않기 때문에 경량 컴포넌트(light  weight component)라고 불린다. 그러므로 스윙 컴포넌트들은 운영체제와 관계없이 항상 동일하게 작동하며 동일한 모양으로 그려진다. 스윙 컴포넌트 AWT 컴포넌트와 구분하기 위해 모두 대문자 J로 시작한다. JFrame, JWindow,  JPanel, JButton, JScrollPane, JTree 등 다양한 컴포넌트가 있다.

 

AWT vs Swing

개발자는 AWT와 스윙 중 택일하여 GUI 응용프로그램을 개발할 수 있는데, 최근에는 거의 모든 GUI 응용프로그램이 스윙 기반으로 작성되고 있는 추세이다.

 

스윙 기반의 GUI 응용프로그램과 스윙 컴포넌트들

  • 응용프로그램의 전체 컴포넌트를 담는 JFrame
  • 모든 메뉴를 담는 JMenuBar
  • 메뉴로 작동하는 JMenu
  • 툴바로 작동하는 JToolBar
  • 버튼으로 작동하는 JButton, 툴바에 부착됨
  • 문자열을 출력하는 JLabel, 툴바에 부착됨
  • 이미지 버튼으로 작동하는 JButton, 툴바에 부착됨
  • 한 줄 문자열을 입력 받는 창 JTextField, 툴바에 부착됨
  • 푸시다운 버튼으로 작동하는 JComboBox, 툴바에 부착됨
  • 두 개의 분리된 팬으로 작동하는 JSplitPane, JFrame에 부착됨
  • 리스트를 출력하는 JList, JSplitPane의 왼쪽에 부착됨
  • 이미지를 출력하는 JLabel, JSplitPnae의 오른쪽에 부착됨
  • JLabel에 출력된 이미지나 텍스트를 스크롤 가능하게 만드는 JScrollPan

 

 

✏️ GUI 패키지

모든 GUI 컴포넌트들은 Component 클래스를 반드시 상속받으며, 스윙 컴포넌트의 클래스 명은 모두 J로 시작한다. AWT 컴포넌트Button, Label 등과 같이 Component를 직접 상속받는 것들과 Panel, Frame 등과 같이 Container를 상속받는 것들이 있다. 그리고 JApplet, JFrame, JDialog를 제외한 모든 스윙 컴포넌트들은 JComponent를 상속받는다.

Swing 클래스, AWT 클래스 AWT와 스윙 클래스의 상속 관계

 

컨테이너

컨테이너란 다른 GUI 컴포넌트를 포함할 수 있는 컴포넌트이다. 즉, 컨테이너는 컴포넌트이면서 컨테이너이고, java.awt.Container 클래스를 상속받아야 한다. 또한, 다른 컨테이너에 컴포넌트로 포함될 수도 있다. 컨테이너로 작동하는 클래스는 아래와 같다.

Frame, Panel, Applet, Dialog, Window // AWT 컨테이너
JFrame, JPanel, JApplet, JDialog, JWindow // 스윙 컨테이너

 

컴포넌트

컴포넌트란 컨테이너와 달리 다른 컴포넌트를 포함할 수 없으며, 컨테이너에 포함되어야 비로소 화면에 출력될 수 있는 GUI 객체이다. AWT나 스윙의 모든 컴포넌트들은 java.awt.Component를 상속받기 때문에 Component 클래스에는 모든 컴포넌트들의 공통적인 속성과 기능이 작성되어 있다. 순수 스윙 컴포넌트들은 모두 javax.swing.JComponent를 상속받는다.

 

최상위 컨테이너

최상위 컨테이너란 다른 컨테이너에 속하지 않고도 독립적으로 화면에 출력될 수 있는 컨테이너를 칭하며 JFrame, JDialog, JApplet의 3가지가 있다.

 

 

✏️ 스윙 GUI 프로그램

스윙 패키지 사용을 위한 import문

import java.awt.*; // 폰트 등 그래픽 처리를 위한 클래스들의 경로명
import java.awt.event.*; // 이벤트 처리에 필요한 기본 클래스들의 경로명
import javax.swing.*; // 스윙 컴포넌트 클래스들의 경로명(스윙 패키지를 이용하기 위해서 사용)
import javax.swing.event.*; // 스윙 이벤트 처리에 필요한 클래스들의 경로명

 

 

스윙 프레임과 컨텐트팬

스윙 프레임은 모든 스윙 컴포넌트들을 담는 최상위 컨테이너로, 컴포넌트들은 스윙 프레임 없이 화면에 출력될 수 없다. 스윙 프레임이 닫히면 프레임 내의 모든 컴포넌트들도 프레임과 함께 화면에서 사라진다.
스윙에서 프레임의 역할을 하는 클래스는 JFrame이고 JFrame 객체는 Frame, MenuBar, Content Pane의 3공간으로 구성된다. MenuBar는 메뉴들을 부착하는 공간이고, Content Pane은 메뉴를 제외한 모든 GUI 컴포넌트들을 부착하는 공간이다.

 

프레임 만들기, JFrame 클래스 상속

// JFrame을 상속받아 MyFrame 클래스 만들기
public class MyFrame extends JFrame{
	...
}

// 스윙 프레임 생성
MyFrame frame = new MyFrame();

// 프레임의 크기와 타이틀 설정
setTtitle("제목");
setSize(폭,높이);
setVisible(true); // 프레임이 출력되로록 지시, false면 화면 출력X

 

300*300 크기의 스윙 프레임 만들기

아래 코드에서 사용하는 setTitle(), setSize(), setVisible() 메소드는 모두 JFrame의 멤버이다. setSize()의 디폴트 값은 0으로 값을 입력하지 않으면 0 x 0이 되어 화면에 출력되지 않으며, setVisible() 메소드 역시 디폴트 값이 false로 true를 입력하지 않으면 화면에 출력되지 않는다.

package ex;
import javax.swing.*;
public class MyFrame extends JFrame{
    public MyFrame(){
        setTitle("300*300 스윙 프레임 만들기");
        setSize(300,300);
        setVisible(true);
    }

    public static void main(String[] args) {
        MyFrame frame = new MyFrame();
    }
}

코드 출력 결과 스윙 프레임 생성

 

프레임에 컴포넌트 붙이기

// 타이틀 달기
public MyFrame() {
    super("타이틀 문자열"); // JFrame() 생성자를 호출하여 타이틀 달기
    setTitle("타이틀 문자열") // 메소드를 호출하여 타이틀 달기
}

// 컨텐트팬에 컴포넌트 달기
public class MyFrame extends JFrame{
    public MyFrame(){
    	...
        Container contentPane = getContentPane(); // 프레임에 부착된 컨텐트팬 알아내기
        JButton button = new JButton("Click"); // 버튼 컴포넌트 생성
        contentPane.add(button); // 컨텐트팬에 버튼 부착
    }
}

// 컨텐트팬에 컴포넌트 달기2(프레임에 부착된 컨텐트팬을 제거하고 새로운 컨텐트팬 붙이기)
class MyPanel extends JPanel{
	// 생성자
}
frame.setContentPane(new MyPanel()); // 프레임의 컨텐트팬을 MyPanel 객체로 변경

 

3개의 버튼 컴포넌트를 가진 스윙 프레임 만들기

package ex;
import javax.swing.*;
import java.awt.*;
public class ContentPaneEx extends JFrame{
    public ContentPaneEx(){
        setTitle("ContentPane와 JFrame");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 프레임 윈도우가 닫힐 때 스윙 프로그램도 함께 종료시키고자 할 때 사용

        Container contentPane = getContentPane();
        contentPane.setBackground(Color.ORANGE);
        contentPane.setLayout(new FlowLayout());

        contentPane.add(new JButton("OK"));
        contentPane.add(new JButton("Cancel"));
        contentPane.add(new JButton("Ignore"));

        setSize(300,150);
        setVisible(true);
    }

    public static void main(String[] args) {
        new ContentPaneEx();
    }
}

※  main() 메소드가 종료한 뒤에도 프레임이 살아 있는 경우가 있음

=> 스윙에서 JFrame 객체가 생성되면 main 스레드 외에, 입력되는 키와 마우스의 움직임을 컴포넌트에게 이벤트로 전달하는 이벤트 처리(분배) 스레드(Event Dispatch Thread)가 자동으로 추가 생성된다. 그러므로 main 스레드가 종료하더라도 이벤트 처리 스레드가 살아 있기 때문에, 자바응용프로그램은 종료되지 않고 사용자로부터 키와 마우스 입력을 계속 처리하게 된다.

 

 

✏️ 컨테이너와 배치

컨테이너마다 배치관리자가 하나씩 존재하며(삭제 가능), 배치관리자는 컨테이너에 컴포넌트가 부착되는 시점에 컴포넌트의 위치와 크기를 결정한다. 또한 컨테이너의 크기가 변경되면 배치관리자는 컨테이너 내부의 모든 컴포넌트들의 위치와 크기를 재조정한다. 배치관리자는 import.java.awt.*; 패키지를 호출해야 하며 종류는 아래와 같다.

  • FlowLayout : 컨테이너에 부착되는 순서대로 왼쪽에서 오른쪽으로 컴포넌트를 배치하고, 오른쪽에 더 이상 배치할 공간이 없으면 아래로 내려와서 다시 왼쪽에서 오른쪽으로 배치한다.
  • BorderLayout : 컨테이너의 공간을 동(EAST), 서(WEST), 남(SOUTH), 북(NORTH), 중앙(CENTER)의 5개의 영역으로 나누고 응용프로그램에서 지정한 영역에 컴포넌트를 배치한다. 응용프로그램에서는 반드시 영역을 지정해야 하며 영역을 지정하지 않으면 중앙에 배치한다.
  • GridLayout : 컨테이너의 공간을 응용프로그램에서 설정한 동일한 크기의 2차원 격자로 나누고, 컴포넌트가 삽입되는 순선대로 좌에서 우로, 다시 위에서 아래로 배치한다.
  • CardLayout : 컨테이너의 공간에 카드를 쌓아 놓은 듯이 컴포넌트를 포개어 배치한다.

컨테이너의 디폴트 배치관리자

AWT와 스윙 컨테이너 디폴트 배치관리자
Window, JWindow BorderLayout
Frame, JFrame BorderLayout
Dialog, JDialog BorderLayout
Panel, JPanel FlowLayout
Applet, JApplet FlowLayout

 

컨테이너의 새로운 배치관리자 설정, setLayout() 메소드

Container.setLayout(LayoutManager.lm); // lm을 새로운 배치관리자로 설정

// 컨텐트팬의 배치관리자를 FlowLayout으로 변경하기
Container contentPane = frame.getContentPane();
contentPane.setLayout(new FlowLayout());

 

 

✏️ FlowLayout 배치관리자

FlowLayout의 생성자와 속성

FlowLayout()

FlowLayout(int align)

FlowLayout(int align, int hGap, int vGap)

  • align: 컴포넌트의 정렬방법, 왼쪽 정렬(FlowLayout.LEFT), 오른쪽 정렬(FlowLayout.RIGHT), 중앙 정렬(FlowLayout.CENTER(디폴트))
  • hGap : 좌우 컴포넌트 사이의 수평 간격, 픽셀 단위, 디폴트는 5
  • vGap : 상하 컴포넌트 사이의 수직 간격, 픽셀 단위, 디폴트는 5

 

FlowLayout 배치관리자 활용

package ex;
import javax.swing.*;
import java.awt.*;
public class FlowLayoutEx extends JFrame{
    public FlowLayoutEx(){
        setTitle("FlowLayout Sample");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Container c = getContentPane();

        // 컨텐트팬에 FlowLayout 배치관리자 설정
        c.setLayout(new FlowLayout(FlowLayout.LEFT,30,40));
        c.add(new JButton("add"));
        c.add(new JButton("sub"));
        c.add(new JButton("mul"));
        c.add(new JButton("div"));
        c.add(new JButton("Calculate"));

        setSize(300,200);
        setVisible(true);
    }

    public static void main(String[] args) {
        new FlowLayoutEx();
    }
}

 

 

✏️ BorderLayout 배치관리자

BorderLayout의 생성자와 속성

void add(Component comp, int index) comp 컴포넌트를 index 위치에 삽입한다.

  • comp: 컨테이너에 삽입되는 컴포넌트
  • index: 컴포넌트의 위치 => 동(BorderLayout.EAST), 서(BorderLayout.WEST), 남(BorderLayout.SOUTH), 북(BorderLayout.NORTH), 중앙(BorderLayout.CENTER)

BorderLayout()

BorderLayout(int hGap, int vGap)

  • hGap: 좌우 두 컴포넌트 사이의 수평 간격, 픽셀 단위, 디폴트는 0
  • vGap: 상하 두 컴포넌트 사이의 수직 간격, 픽셀 단위, 디폴트는 0

BorderLayout 배치관리자 활용

package ex;
import javax.swing.*;
import java.awt.*;
public class BorderLayoutEx extends JFrame{
    public BorderLayoutEx(){
        setTitle("BorderLayout Sample");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Container c = getContentPane();

        c.setLayout(new BorderLayout(30,20));
        c.add(new JButton("Calculate"),BorderLayout.CENTER);
        c.add(new JButton("div"),BorderLayout.EAST);
        c.add(new JButton("mul"),BorderLayout.WEST);
        c.add(new JButton("add"),BorderLayout.NORTH);
        c.add(new JButton("sub"),BorderLayout.SOUTH);

        setSize(300,200);
        setVisible(true);
    }

    public static void main(String[] args) {
        new BorderLayoutEx();
    }
}

 

 

 

✏️ GridLayout 배치관리자

GridLayout의 생성자와 속성

GridLayout()

GridLayout(int rows, int cols)

GridLayout(int rows, int cols, int hGap, int vGap)

  • rows: 그리드의 행 수, 디폴트는 1
  • cols: 그리드의 열 수, 디폴트는 1
  • hGap: 좌우 컴포넌트 사이의 수평 간격, 픽셀 단위, 디폴트는 0
  • vGap: 상하 컴포넌트 사이의 수직 간격, 픽셀 단위, 디폴트는 0

GridLayout으로 입력 폼 만들기

package ex;
import javax.swing.*;
import java.awt.*;
public class GridLayoutEx extends JFrame{
    public GridLayoutEx(){
        setTitle("GridLayout Sample");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        GridLayout grid = new GridLayout(4,2);
        grid.setVgap(5);

        Container c = getContentPane();
        c.setLayout(grid);
        c.add(new JLabel("이름"));
        c.add(new JTextField(""));
        c.add(new JLabel("학번"));
        c.add(new JTextField(""));
        c.add(new JLabel("학과"));
        c.add(new JTextField(""));
        c.add(new JLabel("과목"));
        c.add(new JTextField(""));

        setSize(300,200);
        setVisible(true);
    }

    public static void main(String[] args) {
        new GridLayoutEx();
    }
}

 

 

✏️ 배치관리자가 없는 컨테이너

배치관리자가 없는 컨테이너가 필요한 경우

  • 컴포넌트의 크기나 위치를 개발자가 결정하고자 하는 경우
  • 게임 프로그램과 같이 시간이나 마우스/키보드의 입력에 따라 컴포넌트들의 위치와 크기가 수시로 변하는 경우
  • 여러 컴포넌트들이 겹치는 효과를 연출하고자 하는 경우

컨테이너의 배치관리자 제거

// Container의 setLayout() 메소드를 이용하여 컨테이너의 배치관리자 제거
container.setLayout(null);

// JPanel에 부착된 배치관리자 제거
JPanel p = new JPanel();
p.setLayout(null);

 

컴포넌트의 절대 위치와 절대 크기 설정

배치관리자가 없는 컨테이너에 컴포넌트를 삽입할 때는 응용프로그램에서 컴포넌트의 크기와 위치를 직접 설정하여야 한다. 컴포넌트의 절대 위치와 크기를 설정하기 위해서 java.awt.Component 클래스의 메소드를 이용한다.

void setSize(int width, int height) // 컴포넌트의 크기 설정
void setLocation(int x, int y) // 컴포넌트의 왼쪽 상단 모서리의 좌표 설정
void setBounds(int x, int y, int width, int height) // 크기와 위치 동시 설정

 

배치관리자 없는 컨테이너에 컴포넌트를 절대 위치와 절대 크기로 지정

package ex;
import javax.swing.*;
import java.awt.*;
public class NullContainerEx extends JFrame {
    public NullContainerEx(){
        setTitle("Null Container Sample");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        Container c = getContentPane();
        c.setLayout(null);

        JLabel la = new JLabel("Hello, Press Buttons!");
        la.setLocation(130,50);
        la.setSize(200,20);
        c.add(la);

        for(int i=1;i<=9;i++){
            JButton b = new JButton(Integer.toString(i));
            b.setLocation(i*15, i*15);
            b.setSize(50,20);
            c.add(b);
        }

        setSize(300,200);
        setVisible(true);
    }

    public static void main(String[] args) {
        new NullContainerEx();
    }
}

반응형
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/07   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
글 보관함