레이아웃 메니저(LayoutManager)

자바에서 컨테이너안에 버튼이나 체크박스 같은 컴포넌트를 보기좋게 배치하는 일은 쉬운 일이 아닙니다. 그럴때 레이아웃 메니저를 사용하면 됩니다. 레이아웃 메니저는 컨테이너가 컴포넌트를 어떻게 배치할 것인지를 도와주는 클래스들입니다. 여기서 소개서는 레이아웃 4개를 소개합니다. 그 4개가 BorderLayout, FlowLayout, GridLayout, CardLayout입니다. 이번 포스팅은 이 4개의 레이아웃 메니저에 대해 무슨 특징이 있고 어떻게 사용하면 되는 것인지 알아보도록 하겠습니다.

공통적으로 컨테이너에게 레이이웃 메니저를 적용시키려면 setLayout메소드로 사용할 LayoutManager를 지정해주시면 됩니다. 

1. BorderLayout

BorderLayout은 컴포넌트를 동, 서, 남, 북, 중앙으로 배치시킵니다. 아래의 코드를 통해서 화면배치가 어떻게 이루어지는 지 확인해봅시다.

public class Main {
	
	public static void main(String[] ar){
		Frame frame=new Frame("Reakwon");
		
		frame.setSize(500,300);
		frame.setLayout(new BorderLayout());
		Button eastButton=new Button("East");
		Button westButton=new Button("West");
		Button southButton=new Button("South");
		Button northButton=new Button("North");
		Button centerButton=new Button("Center");
		
		frame.add("East",eastButton);
		frame.add("West",westButton);
		frame.add("South",southButton);
		frame.add("North",northButton);
		frame.add("Center",centerButton);
		
		frame.setVisible(true);
	}
}

BorderLayout

 

Frame의 add()로 위치도 같이 지정해줍니다. add("위치", Component) 또는 add(Component, "위치")로 구분없이 사용할 수 있습니다. 이때 위치의 종류에는 "East", "West", "South", "North", "Center" 가 있는데, 각각은 동, 서, 남, 북, 가운데의 위치를 나타냅니다. 앞글자는 항상 대문자여야합니다.

Panel 사용하기 - 다른 Component를 더 배치

이렇게 버튼 5개만 추가하기보다는 가운데에 더 많은 Component를 결합하여 Frame을 구성하고 싶다면 어떻게하면 좋을까요? 이때 사용할 수 있는 것이 Panel입니다. Panel은 Frame과 같이 자신의 영역이 있어서 그 안에서 다른 Component를 구성할 수 있습니다. Panel은 두 종류가 있는데, 자신의 영역에서 담고 있는 컴포넌트들이 넘친다면 스크롤되지 않는 Panel과 스크롤될수 있는 ScrollPane이 있습니다. 여기서는 단순 Panel만을 사용하는 예를 보도록 하겠습니다.

public static void main(String[] ar){
	Frame frame=new Frame("Reakwon");
	frame.setSize(500,300);
	frame.setLayout(new BorderLayout());
	Button eastButton=new Button("East");
	Button westButton=new Button("West");
	Button southButton=new Button("South");
	Button northButton=new Button("North");
		
    //Panel의 Component 추가    
	Panel panel=new Panel(new BorderLayout());
	Button panelSouth=new Button("Panel_South");
	Button panelNorth=new Button("Panel_North");
	Button panelCenter=new Button("Panel_Center");
	panel.add("South",panelSouth);
	panel.add("North",panelNorth);
	panel.add("Center",panelCenter);
		
		
	frame.add("East",eastButton);
	frame.add("West",westButton);
	frame.add("South",southButton);
	frame.add("North",northButton);
    //Center에 panel 추가
	frame.add("Center",panel);
		
	frame.setVisible(true);
}

 

Frame과 별 차이가 있나요? Frame과 같이 add로 버튼을 추가할 수 있습니다. 그리고 Frame은 그런 Panel을 추가할 수 있죠. 왜냐면 Panel 역시 Component이니까요. 다음 보이는 배치가 위 코드의 결과입니다.

 

간격 넓히기

BorderLayout의 생성자를 주어서 상하 좌우 간격을 조절 할 수 있습니다. 아래처럼 생성자를 이용하는 방법이 있습니다. 처음 arguement는 Horizontal(좌우)의 간격, 두번째는 Vertical(상하)의 간격입니다.

frame.setLayout(new BorderLayout(10,2));

 

생성자를 사용하지 않고 이미 생성된 객체에서 setHgap과 setVgap을 통해서도 바꿀 수 있습니다. 위의 생성자를 통한 간격은 아래의 메소드를 통한 간격 조정과 동일하게 됩니다.

	BorderLayout layout=new BorderLayout();
	layout.setHgap(10);
	layout.setVgap(2);
	frame.setLayout(layout);

 

어떻게 변하는지 볼까요?

 

2. FlowLayout

이름부터 직관적으로 알 수 있듯이 기본적으로 물 흐르듯 먼저 더해진 Component들이 왼족에서 오른쪽으로 추가되고  모두 가운데로 정렬이 되며 자리가 모자라면 아랫줄에 Component들이 배치됩니다. 아래와 같이 FlowLayout을 사용하여 Layout 배치를 해보도록 하겠습니다.

public class Main {
	
	public static void main(String[] ar){
		Frame frame=new Frame("Reakwon");
		frame.setSize(500,300);
		frame.setLayout(new FlowLayout());
		
		for(int i=1;i<=10;i++) {
			frame.add(new Button("Button"+i));
		}
		
		frame.setVisible(true);
	}
}

 

setLayout으로 frame의 레이아웃을 FlowLayout으로 정하고 난 이후에 Frame에 버튼 10개를 추가해줍니다. 이런 Frame이 결과로 보여질겁니다.

Flowlayout1

 

왼쪽부터 차례대로 버튼이 추가되는 것을 알 수 있습니다. 이 프레임 사이즈를 줄여보세요. 자리가 모자르면 아래처럼 밑으로 버튼들이 내려가는 것을 확인할 수 있습니다.

Flowlayout2

 

정렬하는 방법에는 왼쪽정렬(FlowLayout.LEFT), 가운데 정렬(FlowLayout.CENTER), 오른쪽 정렬(FlowLayout.RIGHT)이 있고 간격도 역시 조정할 수 있습니다. 이 모든것은 생성자를 통해서도 가능하고 메소드를 통해서도 가능합니다. 간격 조정은 BorderLayout과 같고, 정렬하는 메소드는 setAlignment()를 이용하면 됩니다. 

위의 코드에서 생성자를 이렇게 고쳐봅시다.

frame.setLayout(new FlowLayout(FlowLayout.RIGHT,10,20));	//오른쪽 정렬, 좌우 간격, 상하 간격

 

그러면 정렬과 간격이 변한것을 볼 수 있습니다.

 

3. GridLayout

격자형태의 Component를 배치하고 싶다면 GridLayout을 사용하시면 됩니다. 기본적으로 생성자에 아무것도 없다면 한 행에 컴포넌트를 배치합니다. 그래서 행과 열의 수를 지정하여 사용합니다. 

GridLayout을 이용해서 Component를 배치해봅시다.

public static void main(String[] ar){
	Frame frame=new Frame("Reakwon");
	frame.setSize(500,300);
		
	frame.setLayout(new GridLayout(4, 3, 10, 3)); //행, 열 , 좌우 간격, 상하 간격
	for(int i=1;i<=9;i++) {
		frame.add(new Button(""+i));
	}
	frame.add(new Button("*"));
	frame.add(new Button("0"));
	frame.add(new Button("#"));
		
	frame.setVisible(true);
}

 

4행 3열의 격자 형태의 레이아웃을 사용했습니다. 그리고 좌우의 간격, 상하의 간격도 주어 Component를 떨어뜨렸지요. 보통 계산기 같은 버튼의 격자형 배치를 만들때 GridLayout이 많이 사용되며 사진의 격자형 배치고 GridLayout을 사용할 수 있습니다.

GridLayout

 

 

4. CardLayout

CardLayout은 카드를 겹쳐놓은듯이 배치하고 이전의 카드, 다음의 카드를 보여주듯 Component 또는 Container를 보여줍니다. 사용법은 아래와 같습니다.

public static void main(String[] ar){
	Frame frame=new Frame("Reakwon");
	frame.setSize(500,300);
		
	Panel card1=new Panel();
	card1.setBackground(Color.DARK_GRAY);
	card1.add(new Label("Card 1"));
		
	Panel card2=new Panel();
	card2.setBackground(Color.ORANGE);
	card2.add(new Label("Card 2"));
		
	CardLayout layout=new CardLayout();
	frame.setLayout(layout);
		
		//card1의 이름은 "card1" 
	frame.add(card1, "card1");
    	//card2의 이름은 "card2"
	frame.add(card2, "card2");
		
	layout.show(frame, "card1");
	frame.setVisible(true);
	
    //5초 대기
	try {
		Thread.sleep(5000);
	}catch(InterruptedException e) {
		e.printStackTrace();
	}
	//5초 후 frame에 추가한 다음 card를 보여줌
	layout.next(frame);
}

 

여기에는 Panel을 두개 사용하여 card1과 card2라는 변수로 이름을 정해줍니다. 이 둘을 구분하기 위해서 배경색과 이름을 보여주는 Label을 추가했습니다. Frame은 CardLayout으로 세팅하는데, 여기서 객체를 계속사용해야하니까 객체를 생성하여 setLayout의 인자로 전달해줍니다. 그리고 차례대로 card1, card2를  Frame에 추가하죠. 이제 가장 처음 보여야할 container를 정하는데 show()메소드를 이용합니다. 

그럼 현재 보이는 것은 card1입니다. 그리고 5초를 기다린 후 next() 메소드로 카드를 다음 것으로 바꿔줍니다. CardLayout은 메소드에 Container를 전달해줘야하는데, CardLayout이 설정된 Container를 전달하면 되는데 여기서는 frame이라는 개체가 그 Container입니다. 이 밖에도 처음, 마지막의 카드로 바꿔줄때는 아래와 같이 사용하면 됩니다.

layout.first(frame);
layout.last(frame);

 

우리가 구현한 위 코드의 결과는 아래처럼 처음 보이는 것은 card1입니다.

Card1

이후에 5초가 흐르면 card2 패널로 바뀌죠.

 

아직은 Event에 대해서 자세히 배우지 않았기 때문에 Thread를 잠시 sleep 시킨후 다음 카드로 변경했는데, Event를 배우면 버튼과 이것 저것을 합쳐서 Card를 바꿀 수 있습니다. 

 

이처럼 JAVA AWT에서 사용하는 LayoutManager에 대한 기본적인 개념과 사용법을 알아보았습니다. 어려운 개념이 있었나요? 우리는 LayoutManager를 사용하여 Component를 효율적으로 그리고 쉽게 배치할 수 있습니다. 이 LayoutManager들은 Swing에서도 그대로 사용됩니다.

 

반응형
블로그 이미지

REAKWON

와나진짜

,

AWT(Abstract Window Toolkit)

AWT는 이름에서도 알 수 있듯이 Window프로그래밍을 하기 위한 GUI(Graphical User Interface)의 도구입니다. GUI가 무엇인지 모르시나요? 여러분이 Windows의 운영체제를 사용한다면 여기 보이는 화면들이 GUI라고 한답니다. 이전의 컴퓨터들은 명령어 방식의 UI를 썼다면 이제 그래픽이 추가되어 X버튼을 눌러 창을 닫고 하고 있지요. 그리고 JAVA는 AWT를 이용해서 윈도우의 GUI로 된 프로그램을 제작할 수 있습니다. 우리가 AWT를 클래스들을 이용하려면 java.awt.*과 동작에 대한 정의를 하려면 java.awt.event.*를 import하여 사용해야합니다.

이제 본격적으로 AWT에 대해서 알아보도록 하겠습니다. GUI에서 각각의 요소들을 우리는 컴포넌트라고 하며 클래스의 상속 계층도에서 메뉴(MenuComponent)를 제외한 모든 컴포넌트는 Component라는 클래스를 상속받고 있습니다. 이 컴포넌트 중에 조금 특별한 컴포넌트가 있는데 그 이름은 컨테이너(Container)입니다. 이름에서도 알 수 있듯이 무엇을 포함하는 클래스인것 같죠? 다른 컴포넌트를 포함하거나 컨테이너도 포함할 수 있습니다. 그래서 우리는 처음 시작할때 이 Container부터 배울 겁니다. 그 중 가장 일반적인 컨테이너는 Frame이라고 합니다.

아참, AWT보다 자바에서 진보적인 GUI는 Swing입니다. Swing이 여러면에서 더 성능이 좋긴한데, 사용법은 AWT와 거의 동일하므로 AWT 먼저 배우고 난 이후에 Swing 컴포넌트를 배워도 상관없습니다. 그리고 AWT 그래픽이 우리한테는 더 친숙할 겁니다. Swing컴포넌트들은 앞에 J가 붙습니다. 예를들어 Frame의 Swing컴포넌트 버전은 JFrame이죠.

이제는 코드를 짜면서 Frame이 무엇인지 알아보고 어떤 기능이 있는지 배워봅시다.

Frame 알아보기

우선 아래의 코드를 쓰고 실행해봅시다. 

import java.awt.*;
public class Main {
	
	public static void main(String[] ar){
		Frame frame=new Frame("Title!");
		frame.setSize(500,300);
		
	}
}

 

Frame을 생성하는 코드인데 생성자에는 Title명을 받는 생성자를 사용했습니다. 그리고 너비와 높이는 500, 300 pixel로 맞춰줍니다. 그리고 실행을 하면 아무것도 뜨지 않습니다. 왜냐면 프레임을 보이게 하려면 setVisible()을 true로 설정해야 보이기 때문이죠. 그래서 위 코드를 아래와 같이 수정해보면 이제 Frame이라는 것이 나올 겁니다.

public static void main(String[] ar){
	Frame frame=new Frame("Title!");
	frame.setSize(500,300);
	frame.setVisible(true);
}

 

자, Frame이 생성되었다는 것을 확인할 수 있습니다. 그리고 Title부분은 우리가 지정한 문자열과 같다는 것을 알 수 있습니다. 이제 구경했으니 닫아봅시다. 

Frame

 

닫히시나요? X버튼을 클릭해도 아무런 변화가 없다는 것을 알 수 있을 겁니다. 왜냐면 X버튼이 눌렸을때 JAVA가 이 프로그램을 닫아야하는지, 혹은 멈춰야하는지, 또는 확인 종료를 묻는 대화창을 띄어야하는지 우리가 정의를 해준적이 없죠. 그래서 X버튼을 눌렸을때를 우리는 Event, 즉 X버튼을 누르는 Event가 발생했다고 하고 동작을 처리해주는 것을 우리는 EventHandling이라고 합니다. 아직은 배우지 않았으니 Eclipse의 화면에 아래의 빨간색을 눌러 종료합시다.

 

X버튼 이벤트 발생시 Handling - WindowListener 추가하기

혹은 잠깐 맛보고 싶다면 아래의 코드를 추가하고 X버튼을 눌러보세요. 추가하기전에 import java.awt.event.*를 하여 import해주세요.

	frame.setVisible(true);
	frame.addWindowListener(new WindowListener() {

		@Override
		public void windowOpened(WindowEvent e) {}

		@Override
		public void windowClosing(WindowEvent e) {
			// TODO Auto-generated method stub
			e.getWindow().setVisible(false);	//보이지 않게	
			e.getWindow().dispose();			//메모리에서 제거
			System.exit(0);						//프로그램 종료
		}

		@Override
		public void windowClosed(WindowEvent e) {}
		@Override
		public void windowIconified(WindowEvent e) {}
		@Override
		public void windowDeiconified(WindowEvent e) {}
		@Override
		public void windowActivated(WindowEvent e) {}
		@Override
		public void windowDeactivated(WindowEvent e) {}
			
	});

 

setLocation() 으로 위치 조정

Frame이 자꾸 왼쪽 구석에만 뜨는데, 여간 불편한게 아니죠. 이때 위치를 조정할 수 있도록 setLocation() 메소드가 존재합니다. 위치는 Frame의 가장 왼쪽, 위 꼭지점을 위치로 잡습니다. 이것도 역시 pixel단위로 화면 왼쪽(x축)에서의 거리, 그리고 화면 위쪽에서의 거리(y축)를 지정할 수 있습니다. 화면 가운데에 Frame을 위치시키려면 이렇게 하면 됩니다. 

x축 위치 = (모니터의 화면 너비/2) - (프레임 너비/2)

y축 위치 = (모니터의 화면 높이/2) - (프레임 높이/2)

모니터의 화면 너비와 높이를 얻어오려면 Toolkit 클래스를 이용해서 아래의 코드처럼 구현하면 됩니다.

	frame.setSize(500,300);
	Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
	frame.setLocation((dim.width/2)-(frame.getWidth()/2), (dim.height/2)-(frame.getHeight()/2));
	frame.setVisible(true);

 

이 후 실행하게 되면 Frame이 정중앙에 보이는 것을 확인할 수 있습니다. 하지만 이것보다 더 간편한 방법이 존재하는데요. 위의 dim과 setLocation의 두줄이 아래 한줄로 표현될 수 있습니다. 바꿔서 실행해도 정중앙에 보이는것을 확인할 수 있습니다.

frame.setLocationRelativeTo(null);

 

배경색을 지정하기 - setBackground()

조금 심심할 수도 있으니 setBackground() 메소드로 배경색을 지정할 수도 있습니다. setBackground()에 전달할 Color의 객체를 사용한다면 원하는 색으로 바꿔줄 수 있습니다. 

frame.setBackground(new Color(180,211,211));

 

또는 Color의 static 멤버로도 가능하긴 합니다.

add 메소드로 다른 Component 추가해보기

Frame에서 다른 Component를 추가해보려면 add 메소드를 이용하면 됩니다. 여기서는 Button 컴포넌트를 사용해서 버튼을 추가해봤습니다. 

	Button button = new Button("My Button");
	frame.add(button);

 

아래처럼 버튼이 Frame을 꽉채운 것을 볼 수 있습니다. 그리고 아무리 눌러봤자 우리는 event를 handling하지 않았으므로 아무런 변화가 없습니다. 

 

이처럼 버튼 뿐만 아니라 다른 Component들도 add메소드로 추가가 가능합니다. 예를들어 체크박스 (Checkbox), 라디오 버튼(RadioButton) 등 말이죠. 한번 JAVA API doc을 참고하여 추가해보고 가지고 놀아보세요.

이상으로 Frame에 관한 간략한 사용법을 알아보았습니다. 다음 포스팅도 GUI의 포스팅을 이어나가도록 하겠습니다.

반응형
블로그 이미지

REAKWON

와나진짜

,

MessageFormat

MessageFormat클래스는 양식에 맞게 메시지를 형식화하는 편리한 클래스입니다. 주로 DB query에 이 MessageFormat이 쓰이는데, 한번 코드를 보면서 이해하도록 하겠습니다.

기본적인 클래스 사용법은 이렇습니다. 

MessageFormat format=new MessageFormat(
		"Name : {0}\n"+
		"Age : {1}\n"+
		"Name, Age : {0}, {1}");
String[] args= {"reakwon","7"};
System.out.println(format.format(args));

 

중괄호의 숫자가 Arguement들의 인덱스를 나타냅니다. Arguement들은 배열의 행태로 위의 args변수에 문자열 배열로 담겨있습니다. 그래서 {0}은 "reakwon", {1}은 "7"로 치환되게 됩니다. 그래서 그 결과는 아래와 같습니다. 

Name : reakwon
Age : 7
Name, Age : reakwon, 7

 

이런 MessageFormat의 사용처는 MySQL과 같은 query에 주로 사용합니다. SELECT * FROM my_table WHERE id = 'reakwon' 이런 쿼리들을 일반화할때 SELECT * FROM {0} WHERE {1} = '{2}' 식으로 사용할 수가 있죠.

MessageFormat format=new MessageFormat(
		"SELECT * FROM {0} WHERE {1} = {2}");
String[] args= {"my_table","id","'reakwon'"};
System.out.println(format.format(args));

 

결과

 

SELECT * FROM my_table WHERE id = 'reakwon'

 

static 메소드로 객체 생성하지 않고 사용할 수도 있습니다. 일회성으로 사용하려면 아래의 방법으로 간편하게 사용할 수도 있지요. MessageFormat의 static 메소드를 바로 사용하는 것을 알 수 있죠.

	String message="SELECT * FROM {0} WHERE {1} = {2}";
	String[] args= {"my_table","id","'reakwon'"};
	System.out.println(MessageFormat.format(message,args));

 

날짜 형식 

MessageFormat은 문자열로만 받는 것은 아닙니다. 날짜와 시간도 이런식으로 받아볼 수 있습니다. 아래의 예시처럼 출력할 수도 있습니다. 

	String message= "오늘 Date: {0,date}, Time :{0,time}";
	System.out.println(MessageFormat.format(message, new Date()));

 

결과

 

오늘 Date: 2021. 4. 6., Time :오전 12:04:34

 

쉼표와 date, time 등으로 날짜와 시간도 지정할 수 있습니다. new Date()로 시간과 날짜를 볼 수 있습니다. 이때 더 많은 정보를 보고 싶다면 아래처럼 사용하면 됩니다.

String message= "오늘 Date: {0,date,full}, Time :{0,time,full}";
System.out.println(MessageFormat.format(message, new Date()));

 

아래와 같이 요일까지 출력이되며 시간 같은 경우에는 나라의 정보도 확인할 수 있습니다.

 

오늘 Date: 2021년 4월 6일 화요일, Time :오전 12시 7분 11초 대한민국 표준시

 

반대로 간략한 정보를 원한다면 short로 바꿔서 입력해주면 됩니다. 더 많은 FormatType과 FormatStyle을 보시려면 지원하는 형식은 아래를 참고해주세요. 

java8 api document

 

기존의 형식 패턴을 applyPattern()으로 다시 지정해서 사용할 수도 있습니다. 이런 방식은 static 메소드가 아닌 객체를 만들어서 계속 사용할때 사용하는 방법입니다.

	String message= "오늘 Date: {0,date,short}, Time :{0,time,short}";
	MessageFormat format = new MessageFormat(message);
	Object[] args= {new Date()};
	System.out.println(format.format(args));
		
	String newMessage="자세히 \n"+
			"오늘 Date: {0,date,full}, Time :{0,time,full}";
	format.applyPattern(newMessage);
	System.out.println(format.format(args));
		

 

결과

 

오늘 Date: 21. 4. 6., Time :오전 12:14
자세히 
오늘 Date: 2021년 4월 6일 화요일, Time :오전 12시 14분 29초 대한민국 표준시

 

자, 여기까지 MessageFormat에 대한 소개와 사용 예제를 알아보았습니다. 이런 형식 클래스들은 유용한 경우가 많으니 알아두시면 좋을 것 같습니다.

반응형
블로그 이미지

REAKWON

와나진짜

,