728x90

만약 한구역에 두개이상의 컴포넌트를 배치하면 어떻게 될까?

백문이 불여일견이니 한번 해보도록 하자.


import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class TestSwing {
public static void main(String[] args) {
JFrame fr = new JFrame("This 프레임");
JPanel pn = new JPanel();
JButton[] bt = new JButton[10];

for (int i = 0; i < bt.length; i++) {
bt[i] = new JButton("Button" + i);
pn.add(bt[i]);
}

fr.setContentPane(pn);

fr.setSize(400, 300);
fr.setVisible(true);
}
}


이 코드를 실행해보자. 어떠한 결과가 나오는가? 버튼을 10개를 배치해보았다.



버튼이 순서대로 배치되었고 가운데로를 기준으로 정렬된것을 알 수있다.

이제 이 프레임 크기를 늘려보자.



늘리면 늘린 크기에 반응해서 버튼들이 늘어난 것을 알 수있다.


이렇듯 사실 모든 프레임과 모든 패널은 기본적으로 레이아웃이 장착되어있다.

레이아웃은 특정 패널이나 프레임 같은 컨테이너들 안에 컴포넌트를 어떻게 배치할지에 대한 방법이다.

지금 까지는 레이아웃을 특별히 지정해서 배치하지 않았으므로 디폴트 레이아웃이 적용되었다.

그러나 이제는 직접 레이아웃을 사용해서 배치해보자.



swing에서 사용가능한 레이아웃은 위와같다.

모두 다 알아보기에는 시간이 부족하므로 가장 자주쓰이는 몇가지를 알아보도록 하자.


FlowLayout

import java.awt.FlowLayout;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class TestSwing {
public static void main(String[] args) {
JFrame fr = new JFrame("This 프레임");
JPanel pn = new JPanel();
JButton[] bt = new JButton[10];

FlowLayout fl = new FlowLayout();
fl.setAlignment(FlowLayout.CENTER);
pn.setLayout(fl);

for (int i = 0; i < bt.length; i++) {
bt[i] = new JButton("Button" + i);
pn.add(bt[i]);
}

fr.setContentPane(pn);

fr.setSize(400, 300);
fr.setVisible(true);
}
}

flowlayout은 가장 기초적이며 상당히 자주 쓰이는 레이아웃이다.

이 레이아웃을 실행해보자. 어떠한 결과가 나오는가?

아마 위와 같은 결과가 나올것이다.

놀랄거 없다. 이 레이아웃은 왼쪽에서 오른쪽으로 차례차례로 쌓이며

내가 선택한 정렬로 정렬이된다. 즉 가운데 정렬이므로 컴포넌트들은 가운데 정렬이된다.

이 레이아웃이 레이아웃을 선택하지 않았을때와 결과가 같은 이유는 이게 패널을 기본 레이아웃이기 때문이다.

그러면 조금 코드를 변경해보자.



정렬을 왼쪽으로 준 코드이다. 이 코드의 결과로 버튼은 왼쪽으로 정렬이 되게 된다.

레이아웃의 정렬방법은 여러가지가 있으므로 찾아서 보도록하자.


BorderLayout


import java.awt.BorderLayout;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class TestSwing {
public static void main(String[] args) {
JFrame fr = new JFrame("This 프레임");
JPanel pn = new JPanel();
JButton[] bt = new JButton[5];

BorderLayout fl = new BorderLayout();
pn.setLayout(fl);

for (int i = 0; i < bt.length; i++) {
bt[i] = new JButton("Button" + i);
pn.add(bt[i]);
}

pn.add(bt[0], BorderLayout.NORTH);
pn.add(bt[1], BorderLayout.EAST);
pn.add(bt[2], BorderLayout.CENTER);
pn.add(bt[3], BorderLayout.WEST);
pn.add(bt[4], BorderLayout.SOUTH);

fr.setContentPane(pn);

fr.setSize(400, 300);
fr.setVisible(true);
}
}


이 레이아웃은 웹 사이트와 같다고 생각하면된다.

동서남북중 총 5가지의 구역으로 나눠져 있다.



컨탠트팬을 배치하지 않는 프레임의 기본 레이아웃이기도 하다.

배치할때 중요한 점은 배치할때 플래그를 지정해주지 않는다면 자동으로 센터에 들어간다는점,

그리고 한 구역에 하나밖에 배치할 수 없다는 점이다.

만약 한구역에 여러개를 배치하고 싶다면 그 안에 패널을 따로 넣어주어야한다.



BorderLayout의 생성자를 보면 hgap과 vgap을 지정해주는 생성자가 있다. 여기서 hgap은 수평 간격을, vgap은 수직 간격을 의미한다.

이 속성을 지정해주면 각각의 지역끼리의 간격이 정해진다.



만약 이 간격을 지정하지 못했더라도 setHgap과 setVgap으로 따로 지정해줄 수 있다.

각각의 속성들은 얼마든지 지정해 줄 수 있기 때문이다.


GridLayout


import java.awt.GridLayout;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class TestSwing {
public static void main(String[] args) {
JFrame fr = new JFrame("This 프레임");
JPanel pn = new JPanel();
JButton[] bt = new JButton[4];

GridLayout gl = new GridLayout(2, 2);
pn.setLayout(gl);

for (int i = 0; i < bt.length; i++) {
bt[i] = new JButton("Button" + i);
pn.add(bt[i]);
}

pn.add(bt[0]);
pn.add(bt[1]);
pn.add(bt[2]);
pn.add(bt[3]);

fr.setContentPane(pn);

fr.setSize(400, 300);
fr.setVisible(true);
}
}


gird는 격자라는 뜻이다. 마치 격차처럼 사용할 수 있는 레이아웃이다.



보다시피 컴포넌트를 총 4개 배치하였다.

우리가 만들때 col을 2로, 또한 row를 2로 하였기 때문이다.

이 레이아웃은 몇가지 규칙이 있다. 규칙은 아래와 같다.

1-열의 갯수이상의 컴포넌트가 필요하다.

2-총 사용가능한 그리드수보단 컴포넌트가 작거나 같아야한다.

또한 실제 보이는 그리드의 갯수는 아래와 같다.


실제 그리드의 갯수 : GridLayout(row,col)로 선언헀을 경우


1-열의 갯수보다 컴포넌트의 수가 적다 : row × 1

2-1의 조건을 충족하면서 그리드수가 컴포넌트수 이하의 경우 : row × col

3-총 그리드 수보다 컴포넌트수가 많을경우 : row × (컴포넌트 수)/2

규칙을 숙지했다면 규칙을 이용해서 한번 만들어보자.


GridBagLayout


import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class TestSwing {
private final static int BUTTON_SIZE = 5;

public static void main(String[] args) {
JFrame fr = new JFrame("This 프레임");
JPanel pn = new JPanel();

JButton[] bt = new JButton[BUTTON_SIZE];
GridBagConstraints[] gbc = new GridBagConstraints[BUTTON_SIZE];

GridBagLayout gbl = new GridBagLayout();
pn.setLayout(gbl);

for (int i = 0; i < BUTTON_SIZE; i++) {
/* Button 초기화 */
bt[i] = new JButton("Button" + i);

/* GridBagConstraints 초기화 */
gbc[i] = new GridBagConstraints();
gbc[i].gridx = i;
gbc[i].gridy = i;

/* Button과 GridBagConstrains Layout지정 */
pn.add(bt[i], gbc[i]);
}

fr.setContentPane(pn);

fr.setSize(500, 500);
fr.setVisible(true);
}
}


위의 GridLayout은 단순히 Grid를 사용한다면 괜찮지만 생각보다 쓰기도 불편하고 자유도도 낮다.

그래서 실제로 격자를 사용하고 싶다면 GridBagLayout이 추천된다.

사실 사용하는 방식은 GridLayout과 비슷한 느낌으로 사용할 수 있다.


GridBagLayout을 사용하려면 전용 격자를 만들어야한다.

그리고 그 전용 격자에 컴포넌트를 배치하는 방식으로 사용한다.

그 전용 격자의 이름은 GridBagConstraints이다.

보면 알겠지만 GridBagLayout에 배치할 GridBagConstraints를 만드는 것을 알 수 있다.


GridBagConstraints속성으로 gridx와 gridy가 존재한다.

이 속성은 각각 어느 위치에 배치할지에 대한 좌표를 의미한다.

예를들어 위의 코드의 경우 gridx와 gridy는 i,i이므로 0,0 그리고 1,1 …같은 형식으로 배치하게 된다.

그럼 실행 결과를 보자.



이렇게 사선으로 배치된걸 알 수 있다.

그럼 두그리드에 한 컴포넌트를 배치할 수 있을까?

그렇다 가능하다. 아래의 예제를 보자.


import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class TestSwing {
private final static int BUTTON_SIZE = 5;

public static void main(String[] args) {
JFrame fr = new JFrame("This 프레임");
JPanel pn = new JPanel();

JButton[] bt = new JButton[BUTTON_SIZE];
GridBagConstraints[] gbc = new GridBagConstraints[BUTTON_SIZE];

GridBagLayout gbl = new GridBagLayout();
pn.setLayout(gbl);

for (int i = 0; i < BUTTON_SIZE; i++) {
/* Button 초기화 */
bt[i] = new JButton("Button" + i);

/* GridBagConstraints 초기화 */
gbc[i] = new GridBagConstraints();
}

gbc[0].gridx = 0;
gbc[0].gridy = 1;
pn.add(bt[0], gbc[0]);

gbc[1].gridx = 0;
gbc[1].gridy = 2;
pn.add(bt[1], gbc[1]);

gbc[2].gridx = 1;
gbc[2].gridy = 0;
pn.add(bt[2], gbc[2]);

gbc[3].gridx = 2;
gbc[3].gridy = 0;
pn.add(bt[3], gbc[3]);

gbc[4].gridx = 1;
gbc[4].gridy = 1;
gbc[4].gridwidth = 2;
gbc[4].gridheight = 2;
pn.add(bt[4], gbc[4]);

fr.setContentPane(pn);

fr.setSize(500, 500);
fr.setVisible(true);
}
}


이 예제를 보면 알 수 있곘지만 4번 버튼의 경우에는 gridwith속성과 gridheight속성을 주었다.

이 속성은 각각 가로와 세로를 원하는 크기로 만들 수 있다.

이제 실행을 해보자.



이렇게 만들어졌다. 보다시피 Button4의경우 gridwith와 gridheight의 지정으로 총 4칸을 차지하게 되었다.

그러나 여러분은 이러한 결과를 원했는가? 아마 버튼 하나가 4칸을 모두 꽉 채우기를 원하였을 것이다.

그래서 새로운 속성이 있다. 바로 fill속성이다.

위 속성을 수정하여 보자.


import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class TestSwing {
private final static int BUTTON_SIZE = 5;

public static void main(String[] args) {
JFrame fr = new JFrame("This 프레임");
JPanel pn = new JPanel();

JButton[] bt = new JButton[BUTTON_SIZE];
GridBagConstraints[] gbc = new GridBagConstraints[BUTTON_SIZE];

GridBagLayout gbl = new GridBagLayout();
pn.setLayout(gbl);

for (int i = 0; i < BUTTON_SIZE; i++) {
/* Button 초기화 */
bt[i] = new JButton("Button" + i);

/* GridBagConstraints 초기화 */
gbc[i] = new GridBagConstraints();
}

gbc[0].gridx = 0;
gbc[0].gridy = 1;
pn.add(bt[0], gbc[0]);

gbc[1].gridx = 0;
gbc[1].gridy = 2;
pn.add(bt[1], gbc[1]);

gbc[2].gridx = 1;
gbc[2].gridy = 0;
pn.add(bt[2], gbc[2]);

gbc[3].gridx = 2;
gbc[3].gridy = 0;
pn.add(bt[3], gbc[3]);

gbc[4].gridx = 1;
gbc[4].gridy = 1;
gbc[4].gridwidth = 2;
gbc[4].gridheight = 2;
gbc[4].fill = GridBagConstraints.BOTH;
pn.add(bt[4], gbc[4]);

fr.setContentPane(pn);

fr.setSize(500, 500);
fr.setVisible(true);
}
}


여기서 새로운 속성이 등장헀는데 fill속성을 BOTH로 주었다.

fill속성의 경우 총 4가지가 존재한다 각각의 의미는 아래와 같다.


fill속성 상수 값


NONE : 아무것도 하지 않는다. 디폴트 값

HORIZONTAL : 수평방향으로 남은 그리드 공간 만큼을 다 채운다.

VERTICAL : 수직방향으로 남은 그리드 공간 만큼을 다 채운다.

BOTH : 모든 방향으로 남은 그리드 공간 만큼을 다 채운다.



이제 원하는 결과가 나왔다.

그리고 또 원하는게 있을 것이다. 이 레이아웃은 GridLayout을 어느정도 대처하려하는데

보면 알겠지만 패널의 모든 공간을 채우지는 않는다.

그러면 패널의 모든 공간을 채우려면 가중치를 둬야한다.

가중치를 두려면 weight를 지정해야한다.


import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class TestSwing {
private final static int BUTTON_SIZE = 5;

public static void main(String[] args) {
JFrame fr = new JFrame("This 프레임");
JPanel pn = new JPanel();

JButton[] bt = new JButton[BUTTON_SIZE];
GridBagConstraints[] gbc = new GridBagConstraints[BUTTON_SIZE];

GridBagLayout gbl = new GridBagLayout();
pn.setLayout(gbl);

for (int i = 0; i < BUTTON_SIZE; i++) {
/* Button 초기화 */
bt[i] = new JButton("Button" + i);

/* GridBagConstraints 초기화 */
gbc[i] = new GridBagConstraints();
}

gbc[0].gridx = 0;
gbc[0].gridy = 1;
gbc[0].weightx = 1;
gbc[0].weighty = 1;
gbc[0].fill = GridBagConstraints.BOTH;
pn.add(bt[0], gbc[0]);

gbc[1].gridx = 0;
gbc[1].gridy = 2;
gbc[1].weightx = 1;
gbc[1].weighty = 1;
gbc[1].fill = GridBagConstraints.BOTH;
pn.add(bt[1], gbc[1]);

gbc[2].gridx = 1;
gbc[2].gridy = 0;
gbc[2].weightx = 1;
gbc[2].weighty = 1;
gbc[2].fill = GridBagConstraints.BOTH;
pn.add(bt[2], gbc[2]);

gbc[3].gridx = 2;
gbc[3].gridy = 0;
gbc[3].weightx = 1;
gbc[3].weighty = 1;
gbc[3].fill = GridBagConstraints.BOTH;
pn.add(bt[3], gbc[3]);

gbc[4].gridx = 1;
gbc[4].gridy = 1;
gbc[4].gridwidth = 2;
gbc[4].gridheight = 2;
gbc[4].weightx = 1;
gbc[4].weighty = 1;
gbc[4].fill = GridBagConstraints.BOTH;
pn.add(bt[4], gbc[4]);

fr.setContentPane(pn);

fr.setSize(500, 500);
fr.setVisible(true);
}
}


weightx와 weighty를 지정한다. 예를 들어서 1을 지정할경우 배율이 1이라는 뜻이다.

아래 실행 결과를 보자.



보면 비율이 1대1대1인걸 알 수 있다.

하나를 2로 둔다면 배율이 두배가 된다. 코드를 살짝 바꿔보자.


import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class TestSwing {
private final static int BUTTON_SIZE = 5;

public static void main(String[] args) {
JFrame fr = new JFrame("This 프레임");
JPanel pn = new JPanel();

JButton[] bt = new JButton[BUTTON_SIZE];
GridBagConstraints[] gbc = new GridBagConstraints[BUTTON_SIZE];

GridBagLayout gbl = new GridBagLayout();
pn.setLayout(gbl);

for (int i = 0; i < BUTTON_SIZE; i++) {
/* Button 초기화 */
bt[i] = new JButton("Button" + i);

/* GridBagConstraints 초기화 */
gbc[i] = new GridBagConstraints();
}

gbc[0].gridx = 0;
gbc[0].gridy = 1;
gbc[0].weightx = 1;
gbc[0].weighty = 1;
gbc[0].fill = GridBagConstraints.BOTH;
pn.add(bt[0], gbc[0]);

gbc[1].gridx = 0;
gbc[1].gridy = 2;
gbc[1].weightx = 2;
gbc[1].weighty = 1;
gbc[1].fill = GridBagConstraints.BOTH;
pn.add(bt[1], gbc[1]);

gbc[2].gridx = 1;
gbc[2].gridy = 0;
gbc[2].weightx = 1;
gbc[2].weighty = 1;
gbc[2].fill = GridBagConstraints.BOTH;
pn.add(bt[2], gbc[2]);

gbc[3].gridx = 2;
gbc[3].gridy = 0;
gbc[3].weightx = 1;
gbc[3].weighty = 2;
gbc[3].fill = GridBagConstraints.BOTH;
pn.add(bt[3], gbc[3]);

gbc[4].gridx = 1;
gbc[4].gridy = 1;
gbc[4].gridwidth = 2;
gbc[4].gridheight = 2;
gbc[4].weightx = 1;
gbc[4].weighty = 1;
gbc[4].fill = GridBagConstraints.BOTH;
pn.add(bt[4], gbc[4]);

fr.setContentPane(pn);

fr.setSize(500, 500);
fr.setVisible(true);
}
}


여기서 1번버튼과 3번 버튼의 배율을 조정했다.



보다시피 두배로 조율이 됬다. 그러나 궁금증이 있을것이다.

왜냐하면 0번과 2번은 배율 1 그대로인데도 수정이 되었다. 이는 fill속성때문이다.

배율은 같은 열이나 같은행단위로 보고 큰 배율이 우선순위로 적용이 된다.


GridBagConstraints의 속성


gridx - 그리드를 배치할 x좌표

gridy - 그리드를 배치할 y좌표

gridwith - 그리드의 가로 크기

gridheight - 그리드의 세로 크기

weightx - 그리드의 크기 x좌표 비율

weighty -그리드의 크기 y좌표 비율

fill - 한 그리드의 컴포넌트의 크기를 채울지 말지를 선택

AbsoluteXYLayout


레이아웃이 조금더 남아있지만 나머지는 설명하기는 조금 어려운 레이아웃들이다.

따라서 마지막으로 소개할 레이아웃은 AbsoluteXYLayout이다.

이 레이아웃은 이때까지의 레이아웃과는 성질이 조금다른데

이때까지 우리는 컴포넌트를 Layout 규칙에 따라 배치했다.

크기를 지정할 수도, 또한 위치를 지정할 수도 없었다.

그러나 이 레이아웃은 내가 원하는 위치, 그리고 원하는 크기에 배치할 수 있다.

바로 절대적인(Absolutely) 위치로배치하는 것이다.



이제는 위치를 지정하기 위해서 메소드로 각각의 컴포넌트마다 위치를 지정해줘야한다.

그때 사용할 메소드는 setBounds인데 각각 x좌표, y좌표, 가로, 세로를 지정해 준다.


import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class TestSwing {
private final static int BUTTON_SIZE = 5;

public static void main(String[] args) {
JFrame fr = new JFrame("This 프레임");
JPanel pn = new JPanel();

JButton[] bt = new JButton[BUTTON_SIZE];
int[] width = {100, 150, 200, 250, 300};
int[] height = {50, 150, 200, 250, 300};
pn.setLayout(null);

for (int i = 0; i < BUTTON_SIZE; i++) {
bt[i] = new JButton("Button" + i);
bt[i].setBounds(100, 50, width[i], height[i]);
pn.add(bt[i]);
}

fr.setContentPane(pn);

fr.setSize(500, 500);
fr.setVisible(true);
}
}


위의 예제는 이제 각각의 x,y,width,height를 지정한 예시이다.

눈여결 볼것은 레이아웃을 특별히 지정하지 않고 null을 사용한것이다.

AbsooluteXYLayout은 레이아웃을 지정하지않고 null값을 지정하면된다.



보다시피 버튼의 위치가 내가 지정한 위치에, 내가 지정한 크기로 배치된것을 확인할 수 있다.

'Programming > Java-Swing' 카테고리의 다른 글

[Swing-06]Event-Key  (0) 2017.10.24
[Swing-05]Event-Action  (0) 2017.10.21
[Swing-03]Component  (0) 2017.10.18
[Swing-02]Swing 시작  (0) 2017.10.18
[Swing-01]AWT  (0) 2017.10.18

+ Recent posts