본문 바로가기

BackEnd/Java

[java] 이것이 자바다 부록 Java UI 1 (Swing)

728x90
반응형

1. Swing

   ▷ UI(User Interface) : 윈도우, 메뉴, 버튼, 라디오, 리스트 등 시각적인 컴포넌트를 제공하고 사용자와 상호작용을 돕는다.

 

   ▷ JDK : 자바 내에서 UI 프로그램 개발 가능 (JFC를 제공)

   ▷ JFC : UI를 만들기 위한 클래스들의 모음(AWT, Swing)

   ▷ AWT : java.awt 패키지, 운영체제 컴포넌트를 그대로 이용, 운영체제들이 공통적으로 가지고 있는 컴포넌트만 사용하므로 컴포넌트 수가 제한적, 

   ▷ Swing : javax.swing 패키지, 자바에서 직접 컴포넌트를 만듬, 자바에서 직접 제공하는 컴포넌트이기 때문에 종류가 매우 다양함

      ▶ 단점 :  자바가 직접 컴포넌트를 생성하기 때문에 AWT에 비해 CPU 와 메모리를 상대적으로 많이 사용

 

1. AWT를 이용한 출력
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Frame;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

// Frame 상속
public class App extends Frame {
	public App() {
		// 제목 설정
		setTitle("AWT App");
		// 윈도우 크기 설정
		setSize(300, 100);
		// Button 추가
		add(new Button("Ok"), BorderLayout.SOUTH);
		
		// 종료 버튼 처리
		addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				System.exit(0);
			}
		});
		
	}
	
	public static void main(String[] args) {
		
		// 윈도우 생성
		App app = new App();
		
		// 윈도우를 보여줌
		app.setVisible(true);
		
	}
}​

 

 

2. Swing을 이용한 출력
import java.awt.BorderLayout;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JButton;
import javax.swing.JFrame;

// Frame 상속
public class App2 extends JFrame {
	public App2() {
		setTitle("Swing App");
		setSize(300, 100);
		getContentPane().add(new JButton("Ok"), BorderLayout.SOUTH);
		
		addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				System.exit(0);
			}
		});
		
	}
	
	public static void main(String[] args) {
		App2 app = new App2();
		app.setVisible(true);
	}
}​

 

 

 

2. 이벤트 디스패칭 스레드

   ▷ Swing은 스레드에 안전하지 않아 작업 스레드들이 동시에 접근해서 UI를 변경하게 되면 문제가 발생할 수 있습니다.

      ▶ 이벤트 디스패칭 스레드(event-dispatching thread)에 의해 순차적으로 UI 변경 작업을 진행하도록 설계됨

 

   ▷ 작업 스레드에서 UI 를 생성, 변경 작업시 작업할 내용을 Runnable 객체로 생성한 뒤, 큐Queue에 저장

      ▶ 이벤트 디스패칭 스레드가 순차적으로 큐에 있는 Runnable 객체를 꺼내어 실행하면서 UI 생성, 변경함


큐는 FIFO로 입력한 순서대로 출력하고 스택은 LIFO로 나중에 입력한 것이 먼저 출력됩니다.

 

   ▷ 작업 스레드는 SwingUtilities 클래스의 invokeLater() 메소드를 이용해서 큐Queue에 Runnable 객체를 저장

      ▶ invokeLater 메서드명 : 큐에 먼저 저장된 Runnable을 처리하고 나중에 처리한다는 의미

 

import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

// JFrame 상속
public class App extends JFrame {
	public App() {
		setTitle("Swing App");
		setSize(300, 100);
		addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				System.exit(0);
			}
		});
		
	}
	
	public static void main(String[] args) {
		
		SwingUtilities.invokeLater(new Runnable(){
			public void run() {
				App app = new App();
				app.setVisible(true);
				
				System.out.println(Thread.currentThread().getName());	
			}
		});		
	}
}

// 출력 : 
// AWT-EventQueue-0

 

3. Swing 컨테이너

NO 컨테이너 클래스 용도
1 JDesktopPane 내부 윈도우를 여러 개 포함할 수 있는 MDI 프로그램을 만들 때 사용
2 JDialog 다이얼로그 윈도우를 만들 때 사용
3 JFrame 작업 표시줄, 메뉴가 제공되는 윈도우를 만들 때 사용
4 JInternalFrame JDesktopPane에 포함되는 내부 윈도우를 만들 때 사용
5 JPanel 컴포넌트들을 배치할 때 사용
6 JScrollPane 수직 또는 수평 스크롤이 필요할 때 사용
7 JSplitPane 수직 또는 수평으로 보여주는 크기를 조절할 때 사용
8 JTabbedPane 여러 가지 탭을 제공할 때 사용
9 JWindow 작업 표시줄, 메뉴가 없는 윈도우를 만들 때 사용

 

   ▷ JWindow, JFrame, JDialog는 완전한 윈도우 창 형태를 갖고 있는 최상위 레벨 컨테이너(TopLevel Containers)

      ▶ 나머지는 최상위 레벨 컨테이너의 내부에서 사용되는 보조 컨테이너들

 

◎ Swing 컨테이너 구조

   ▷ JWindow, JFrame, JDialog, JInternalFrame 컨테이너는 다른 컨테이너와 달리 기본 판(Root Pane) 위에 여러 겹의 판(Pane)으로 구성되어 있음

 

1. GlassPane
   ▷ 다른 패널 위에 존재하면서 기본적으로 숨겨져 있는 투명한 판
      ▶ 버튼이 잘 눌러집니다. 
      ▶ 체크 박스를 누르면 button은 눌러지지 않습니다.

2. JMenuBar와 ContentPane
   ▷ 메뉴가 포함되는 판, 아래 쪽에 있는 ContentPane은 버튼과 같은 UI 컴포넌트가 배치되는 판

JMenuBar는 JFrame의 setJMenuBar() 메소드로 추가할 수 있음.
버튼과 같은 UI 컴포넌트는 JWindow, JFrame, JDialog, JInternalFrame에 직접 배치할 수 없고 getContentPane() 메소드를 이용해서 ContentPane을 얻은 후에 배치

JFrame jFrame = new JFrame();
//MenuBar 추가
jFrame.setJMenuBar(new JMenuBar());
//컴포넌트 추가
jFrame.getContentPane().add(new JButton("확인"), BorderLayout.SOUTH);​


3. LayeredPane
   ▷ 여러 컴포넌트들이 겹쳐질 때 각 컴포넌트의 상하 위치를 결정

   ▷ 손 흔드는 듀크(duke)에 마우스를 올려 놓으면 듀크가 마우스 를 따라 움직인다.
   ▷ 듀크가 Cyan 레이어 위에 위치하기 때문에 지정한 색까지만 맨 앞으로 가져오기를 할 수 있습니다.

 

 

◎ JWindow

   ▷ JWindow는 윈도우 경계선, 제목 표시줄, 메뉴바가 모두 없는 윈도우를 만드는 컨테이너

   ▷ 컴포넌트만 배치할 수 있는 평면 공간만을 가짐.

   ▷ 게임 애플리케이션처럼 제목 표시줄이 없는 윈도우를 만들 때 주로 이용됨

   ▷ 새로운 개발자 정의 윈도우는 다음과 같이 JWindow를 상속해서 만들 수 있음

 

 

◎ JWindow 예제

import java.awt.BorderLayout;
import java.awt.GraphicsEnvironment;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.JWindow;


public class JWindowExample extends JWindow{

	public JWindowExample() {
		//JWindow의 크기
		this.setSize(600,350);
		
		//JWindow를 화면 중앙으로 띄우기
		GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
		Point centerPoint = ge.getCenterPoint();
		int leftTopX = centerPoint.x - this.getWidth()/2;
		int leftTopY = centerPoint.y - this.getHeight()/2;
		this.setLocation(leftTopX, leftTopY);
		
		// JWindow에 이미지가 포함된 JLabel 추가
		JLabel label = new JLabel();
		label.setIcon(new ImageIcon(getClass().getResource("game.png")));
		getContentPane().add(label, BorderLayout.CENTER);
		
		// 마우스 클릭 이벤트 처리
		this.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				dispose();
			}
		});
	}
	
	public static void main(String[] args) {
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				JWindowExample jWindow = new JWindowExample();
				jWindow.setVisible(true);
			}
		});
	}
}



1. 윈도우는 반드시 폭과 높이가 있어야 하기때문에 setSize() 메소드로 폭과 높이를 줍니다.
   ▷ 중앙 지점에서 좌측 상단 모서리의 좌표를 계산해야합니다.

2. GraphincsEnvironment의 getContentPoint() 메소드는 화면 중앙 지점의 X좌표와 Y좌표를 가지고 있는 Point 객체를 리턴합니다. 이렇게 얻은 화면 중앙 좌표와 윈도우 폭, 높이로 JWindow의 좌측 상단 모서리 좌표를 계산할 수 있습니다. 그 후 JWindow의 setLocation() 메소드로 좌 측 상단 모서리 좌표를 설정해주면 됩니다.

3. JWindow를 화면에 띄우려면 setVisible(true) 메소드를 호출하면 됩니다.

4. 반대로 setVisible(false)을 호출하면 JWindow가 화면에서 사라지는데, 이것은 JWindow가 화면에서 완전히 제거되는 것이 아니라 숨겨질 뿐입니다. 다시 setVisible(true)을 호출하면 언제든지 나타납니다. 만약 JWindow를 화면에서 완전히 제거하고 싶다면 dispose() 메소드를 호출하면 됩니다.
   ▷ ex) jWindow.dispose()


실행 결과

 

◎ JFrame

   ▷ JFrame은 JWindow와는 달리 윈도우 경계선, 제목 표시줄, 메뉴바가 있는 윈도우를 만드는 컨테이너 클래스

   ▷ JFrame의 제목 표시줄은 아이콘, 제목, 크기 조절용 버튼, 종료 버튼으로 구성

 

 

◎ JFrame 기능별 상수

NO 기능별 상수 설명
1 WindowConstants.DO_NOTHING_ON_CLOSE 아무 것도 하지 않음
2 WindowConstants.HIDE_ON_CLOSE 화면에서 JFrame 숨김(기본)
3 WindowConstants.DISPOSE_ON_CLOSE 화면에서 JFrame 완전히 제거, 다른 JFrame이 없다면 윈도우 프로세스를 종료
4 JFrame.EXIT_ON_CLOSE 윈도우 프로세스를 종료

 

◎ JFrame 사용 예제

import java.awt.GraphicsEnvironment;
import java.awt.Point;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

public class JFrameExample extends JFrame {
	public JFrameExample() {
		// JWindow의 크기
		this.setSize(600, 500);
		// 제목 표시줄 아이콘, 제목 설정
		this.setIconImage(new ImageIcon(getClass().getResource("icon1.png")).getImage());
		this.setTitle("메인창");
		
		// 종료 버튼의 기본 기능
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		// JWindow를 화면 중앙으로 띄우기
		GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
		Point centerPoint = ge.getCenterPoint();
		int leftTopX = centerPoint.x - this.getWidth()/2;
		int leftTopY = centerPoint.y - this.getHeight()/2;
		this.setLocation(leftTopX, leftTopY);
	}	
	
	public static void main(String[] args) {
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				JFrameExample jFrame = new JFrameExample();
				jFrame.setVisible(true);
			}
		});
	}
}

 

결과창


제목 앞에 이미지가 추가됩니다.

 

◎ JTabbedPane

   ▷ JTabbedPane은 탭tab별로 다른 내용을 보여주 기 위해 사용되는 컨테이너

   ▷ 독립적인 윈도우 모양이 없어 JWindow, JFrame, JDialog 등과 같은 최상위 레벨 컨테이너에 배치됨

 

◎ JTabbedPane 사용 예제

import java.awt.BorderLayout;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.SwingUtilities;

public class JTabbedPaneExample extends JFrame {
	private JTabbedPane jTabbedPane;
	private JPanel tab1Panel;
	private JPanel tab2Panel;
	
	// 메인 윈도우 설정
	public JTabbedPaneExample() {
		this.setTitle("JTabbedPaneExample");
		this.setSize(300, 200);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.getContentPane().add(getJTabbedPane(), BorderLayout.CENTER);
	}
	
	// JTabbedPane
	private JTabbedPane getJTabbedPane() {
		if(jTabbedPane == null) {
			jTabbedPane = new JTabbedPane();
			jTabbedPane.setTabPlacement(JTabbedPane.LEFT);
			jTabbedPane.addTab("탭1", getTab1Panel());
			jTabbedPane.addTab("탭2", getTab2Panel());
		}
		return jTabbedPane;
	}
	
	// Tab1에 추가된 JPanel 생성
	private JPanel getTab1Panel() {
		if(tab1Panel == null) {
			tab1Panel = new JPanel();
			JLabel jLabel = new JLabel();
			jLabel.setIcon(new ImageIcon(getClass().getResource("duke1.gif")));
			tab1Panel.add(jLabel);
		}
		return tab1Panel;
	}
	
	// Tab1에 추가된 JPanel 생성
	private JPanel getTab2Panel() {
		if(tab2Panel == null) {
			tab2Panel = new JPanel();
			JLabel jLabel = new JLabel();
			jLabel.setIcon(new ImageIcon(getClass().getResource("duke2.gif")));
			tab2Panel.add(jLabel);
		}
		return tab2Panel;
	}
	
	
	
	public static void main(String[] args) {
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				JTabbedPaneExample jFrame = new JTabbedPaneExample();
				jFrame.setVisible(true);
			}
		});
	}
}



 

◎ JScrollPane

   ▷ 포함된 컴포넌트의 크기가 JScrollPane 자신보다 큰 경우 수평 또는 수직 스크롤 바를 이용해서 볼 수 있게 함

   ▷ JScrollPane은 다른 컨테이너와는 달리 단 하나의 컴포넌트만을 포함시킬 수 있음

 

◎ JScrollPane 사용 예제

import java.awt.BorderLayout;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;

public class JScrollPaneExample extends JFrame {
	private JScrollPane scrollImage;
	private JLabel lblImage;
	
	// 메인 윈도우 설정
	public JScrollPaneExample() {
		this.setTitle("JScrollPaneExample");
		this.setSize(350, 230);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		// JFrame 중앙에 JScrollPane 추가
		this.getContentPane().add(getScrollImage(), BorderLayout.CENTER);
	}
	
	// JScrollPane 생성
	private JScrollPane getScrollImage() {
		if(scrollImage == null) {
			scrollImage = new JScrollPane(getLblImage());
		}
		return scrollImage;
	}
	
	// JLabel 생성
	public JLabel getLblImage() {
		if(lblImage == null) {
			lblImage = new JLabel();
			lblImage.setIcon(new ImageIcon(getClass().getResource("snow.jpg")));
		}
		return lblImage;
	}
	
	public static void main(String[] args) {
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				JScrollPaneExample jFrame = new JScrollPaneExample();
				jFrame.setVisible(true);
			}
		});
	}
}

 

출력 값

 

자바의 Swing을 이용한 GUI 출력에 대해서 공부해보았습니다.

 

자바의 코드에서 Swing의 메서드들을 이용하면 작은 창에 HTML과 같이 배경을 꾸밀 수있고 이 기능을 이용해서 게임 같은 것들을 만들 수 있다고 합니다.

 

많은 분들의 피드백은 언제나 환영합니다!  많은 댓글 부탁드려요~~

 

728x90
반응형