11.Swing
11.1개요
11.1.1기본개념
11.1.2스윙 컴포넌트 종류
11.1.3스윙 컴포넌트 계층도
11.1.4JComponent
11.2최상위 컨테이너
11.2.1개요
11.2.2프레임
11.2.3대화상자
11.2.4애플릿
11.3레이아웃 관리자
11.3.1개요
11.3.2사용법
11.3.3커스텀 레이아웃
11.4중간 단계 컨테이너
11.4.1패널(JPanel)
11.4.2스크롤창(JScrollPane)
11.4.3스플릿창(JSplitPane)
11.4.4탭창(JTabbedPane)
11.4.5툴바(JToolBar)
11.4.6내부 프레임(JInternalFrame)
11.4.7.1투명창(GlassPane)
11.4.7.2다층창(JLayeredPane)
11.4.7.3메뉴바(JMenuBar)
11.5Event Model
11.5.1Delegation Model
11.5.2Listener
11.5.3Adapter
11.6Componets
11.6.1버튼(JButton, JToggleButton)
11.6.2체크박스(JCheckBox)
11.6.3라디오 버튼(JRadioButton)
11.6.4색상 선택 상자(JColorChooser)
11.6.5콤보박스
11.6.6파일 선택 대화상자
11.6.7레이블
11.6.8목록
11.6.10진행 상태바
11.6.11슬라이더
11.6.12테이블
11.6.13텍스트
11.6.14텍스트 필드
11.6.15툴팁
11.6.16트리
11.Swing
11.1개요
11.1.1기본개념
C:\j2sdk1.4.0\demo\jfc\SwingSet2\SwingSet2.html
Swing 컴포넌트는 AWT(Abstract Window Toolkit) 컴포넌트를 기반으로 만든 JFC(Java Foundation Classes)의 일부분이다. 또한, AWT 컴포넌트와 Swing 컴포넌트는 프로그램의 GUI(graphical user interface)를 만들기 위한 자바 API다. 컴포넌트라 불리는 이유는 AWT, Swing API 모두 Component 클래스를 상속받기 때문이다.
JFC는 아래의 기능을 포함한다.
1)Swing 컴포넌트
2)Pluggable Look and Feel 지원
3)Accessibility API
4)Java 2DTM API
5)Drag and Drop 지원
AWT만으로도 완전한 GUI를 만들 수 있지만 Swing으로만 GUI를 만들도록 권장한다.
AWT와 Swing의 주요한 차이는 아래와 같다.
1)AWT 패키지는 java.awt이고, Swing 패키지는 javax.swing이다(eXtention)
2)AWT와는 달리 Swing 컴포넌트는 특정 플랫폼에 의존적인 코드가 없다
3)Swing은 버튼과 레이블에 이미지도 표시할 수 있다
4)Swing은 직사각형 외의 외양을 갖을 수 있다
Swing 프로그램을 만들 때 주의할 점은 아래와 같다.
1)AWT 컴포넌트와 혼용하지 않는다. 대부분의 AWT 컴포넌트는 중량 컴포넌트고, Swing 컴포넌트는 경량 컴포넌트다. 항상 중량 컴포넌트가 경량 컴포넌트의 상위에 그려지므로 혼용하게 되면 겹쳐서 그릴 수 없다.
2)스윙 컴포넌트의 실현(show(), setVisible(true), pack()) 후에 발생하는 컴포넌트 상태를 변경하는 코드는 반드시 이벤트 처리 부분에서 실행해야 한다.(repaint(), revalidate() 제외)
3)스윙 컴포넌트 컨테이너의 상위에는 스윙 컴포넌트 최상위 컨테이너가 있어야 한다.
자바의 GUI 프로그램
GUI 설계(Graphic User Interface) + 프로그램 로직(Business Logic) + 이벤트 처리
GUI의 좌표체계
그래픽 시스템의 좌표체계는 아래의 그림과 같이 왼쪽 상단(0, 0)에서 오른쪽, 아래로 해상도 만큼 픽셀단위로 증가한다.
11.1.2스윙 컴포넌트 종류
최상위 컨테이너(Top-Level Containers) | ||
JFrame | JApplet |
중간단계 컨테이너(General-Purpose Containers) | ||
JPanel | ||
|
| |
|
|
중간단계 컨테이너(Special-Purpose Containers) | ||
Layered pane |
Editable Displays of Formatted Information | ||
JFileChooser | JTable | |
| ||
JTextArea | JTree |
|
Basic Controls(컴포넌트) | ||
JButton | JToggleButton | JCheckBox |
Borders |
Uneditable Information Displays | ||
11.1.3스윙 컴포넌트 계층도
Component Hierarchy: Part 1--AWT Similar
Component Hierarchy: Part 2--New And Expanded Components
11.1.4JComponent
JComponent 클래스는 최상위 컨테이너를 제외한 거의 모든 스윙 컴포넌트의 선조 클래스다.
java.lang.Object
|
+--java.awt.Component
|
+--java.awt.Container
|
+--javax.swing.JComponent
Component에는 레이아웃, 페인팅, 이벤트 지원등 컴포넌트에 필요한 기본 기능이 있고, Container에는 컨테이너에 컴포넌트를 추가, 배치 등의 기능이 있다.
JComponent의 주요 기능은 아래와 같다.
툴팁(풍선 도움말)
테두리
키보드 액션
외양
속성
레이아웃
더블 버퍼링
아래는 JComponent 클래스의 주요 메서드다.
자료형 | 메서드 / 설명 |
그리기 관련 | |
void void void void void void void | Component.repaint() repaint(Rectangle r) 컴포넌트 전체 또는 일부를 다시 그리도록 update(Graphics g)를 호출을 요청 revalidate() 컴포넌트의 레이아웃 재배치를 요청 paintComponent(Graphics g) paintBorder(Graphics g) paintChildren(Graphics g) // 상속:선조,후손 Swing:부모,자식 paint(Graphics g) |
자료형 | 메서드 / 설명 |
모양 관련 | |
void Border void boolean void Color void Color void Font FontMetrics | setBorder(Border border) getBorder() setOpaque(boolean isOpaque) isOpaque() 불투명한 컴포넌트는 자신의 배경을 배경색으로 채운다 setForeground(Color fg) Component.getForeground() setBackground(Color bg) Component.getBackground() setFont(Font font) Component.getFont() Component.getFontMetrics(Font font) 폰트 관련 정보를 얻을 수 있다 |
자료형 | 메서드 / 설명 |
상태 관련 | |
void boolean void void boolean void Cursor | setVisible(boolean aFlag) isVisible() 최상위 컨테이너를 제외한 컴포넌트는 기본으로 화면에 보인다 setToolTipText(String text) setEnabled(boolean enabled) Component.isEnabled() 사용자 입력에 반응할 수 있고 이벤트를 발생 시킬 수 있다 setCursor(Cursor cursor) Component.getCursor() |
자료형 | 메서드 / 설명 |
컨테이너 관련 | |
Component void RootPane Container | Container.add(Component comp) Container.remove(Component comp) getRootPane() getParent() 컴포넌트를 포함하는 컨테이너를 얻는다 |
자료형 | 메서드 / 설명 |
레이아웃 관련 | |
void void void void | Container.setLayout(LayoutManager mgr) 레이아웃을 설정 setPreferredSize(Dimension preferredSize) setAlignmentX(float alignmentX) setAlignmentY(float alignmentY) X, Y축 정렬을 설정 Component.CENTER_ALIGNMENT Component.BOTTOM_ALIGNMENT Component.LEFT_ALIGNMENT Component.RIGHT_ALIGNMENT Component.TOP_ALIGNMENT |
자료형 | 메서드 / 설명 |
크기, 위치 관련 | |
int int Dimension void int int Rectangle void Point void Point Insets | getWidth() getHeight() getSize(Dimension rv) Component.setSize(Dimension size) 컴포넌트의 크기를 픽셀 단위로 설정하고 얻는다 getX() getY() getBounds(Rectangle rv) Component.setBounds(Rectangle bounds) getLocation(Point rv) setLocation(Point loc) 부모 컨테이너 왼쪽 최상위로부터 컴포넌트의 위치를 설정하고 얻는다 Component.getLocationOnScreen() 스크린 왼쪽 최상위로부터 컴포넌트의 위치를 얻는다 getInsets(Insets rv) 컴포넌트의 밖 여백을 얻는다 |
아래는 관련 클래스와 메서드다
자료형 | 메서드 / 설명 |
java.awt.Rectangle | |
| Rectangle(int x, int y, int width, int height) Point getLocation() Dimension getSize() |
java.awt.Dimension | |
| Dimension(int width, int height) double getHeight() double getWidth() |
java.awt.Point | |
| Point(int x, int y) double getX() double getY() |
java.awt.Insets | |
| Insets(int top, int left, int bottom, int right) |
java.awt.Color | |
| Color(int r, int g, int b) 0-255 Color.red, Color.green, Color.blue, Color.white, Color.black ... |
11.2최상위 컨테이너
11.2.1개요
스윙의 최상위 컨테이너 클래스로 JFrame, JDialog, JApplet이 있다.
컴포넌트가 화면에 나타나기 위해서는 포함관계 계층에 포함되어야 하고, 포함관계 계층의 루트에는 최상위 컨테이너가 있다.
포함관계 계층
컨테이너는 다른 컨테이너나 컴포넌트를 포함한다. 이러한 포함관계를 계층으로 나타낸 것이 포함관계 계층이다.
최상위 컨테이너는 하나의 내용창을 갖는다. 보여질 대부분의 컴포넌트는 내용창안에 추가된다
메뉴바는 내용창 밖, 최상위 컨테이너에 추가된다
11.2.2프레임
프레임이란 테두리, 제목줄, 윈도우 아이콘/최소/종료 버튼 등의 요소들을 갖는 윈도우다. 스윙 어플리케이션은 최소 하나의 프레임을 갖는다. 스윙에서는 JFrame 클래스를 제공한다. 다른 윈도우에 포함되는 윈도우는 내부 프레임을 사용한다.
java.awt.Container
|
+--java.awt.Window
|
+--java.awt.Frame
|
+--javax.swing.JFrame
아래는 JFrame 클래스의 주요 메서드다.
자료형 | 메서드 / 설명 |
생성자 | |
| JFrame(String name) name은 프레임의 이름 |
자료형 | 메서드 / 설명 |
기타 | |
Container void JRootPane Component JLayeredPane void JMenuBar | getContentPane() setContentPane(Container content) getRootPane() getGlassPane() getLayeredPane() setJMenuBar(JMenuBar menubar) getJMenuBar() |
JFrame이 하는 주요한 일은 아래와 같다.
내용창을 얻기
frame.getContentPane().add(yellowLabel, BorderLayout.CENTER);
메뉴바 추가
frame.setJMenuBar(cyanMenuBar);
프레임 크기 지정
frame.pack();
프레임 보이기
frame.setVisible(true);
프레임을 이벤트 리스너에 등록
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class TopLevelDemo {
public static void main(String s[]) {
JFrame frame = new JFrame("TopLevelDemo");
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
JLabel yellowLabel = new JLabel("라벨");
yellowLabel.setOpaque(true);
yellowLabel.setBackground(Color.yellow);
yellowLabel.setPreferredSize(new Dimension(200, 180));
JMenuBar cyanMenuBar = new JMenuBar();
cyanMenuBar.setOpaque(true);
cyanMenuBar.setBackground(Color.cyan);
cyanMenuBar.setPreferredSize(new Dimension(200, 20));
frame.setJMenuBar(cyanMenuBar);
frame.getContentPane().add(yellowLabel, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
}
11.2.3대화상자
JOptionPane, JDialog
11.2.3대화상자
표준 대화상자는 JOptionPane을 커스텀 대화상자는 JDialog를 사용한다.
대화상자는 모달(modal)과 비모달(modeless)로 분류한다. 모달은 대화상자가 닫혀야 다른 윈도우가 사용자 입력을 받을 수 있다. 비모달은 JDialog를 이용한다.
JDialog는 JFrame을 사용하는 것과 비슷한 방법을 사용한다.
JOptionPane은 내부적으로 JDialog를 생성하고 자신을 JDialog의 내용창으로 추가한다.
1)JOptionPane
javax.swing.JComponent
|
+--javax.swing.JOptionPane
아래는 JOptionPane 클래스의 주요 메서드다.
자료형 | 메서드 / 설명 |
생성자 | |
| JOptionPane(Object message, int messageType, int optionType, Icon icon, Object[] options, Object initialValue) 매개변수는 모두 생략가능 message - 표현될 객체(보통 문자열) messageType - ERROR_MESSAGE, INFORMATION_MESSAGE, WARNING_MESSAGE, QUESTION_MESSAGE, PLAIN_MESSAGE optionType - DEFAULT_OPTION, YES_NO_OPTION, YES_NO_CANCEL_OPTION, OK_CANCEL_OPTION icon - 아이콘 이미지 options - 사용자가 선택할 수 있는 옵션(보통 문자열) initialValue - 초기 선택된 옵션 |
대화상자 표시 | |
static void | showMessageDialog(Component parentComponent, Object message, String title, int messageType, Icon icon) messageType에 따른 대화상자, title부터 생략가능 parentComponent - 대화상자가 표시될 프레임, null이면 기본 프레임 사용 title - 대화상자 제목 |
static int | showConfirmDialog(Component parentComponent, Object message, String title, int optionType, int messageType, Icon icon) optionType에 따른 대화상자, title부터 생략가능 선택된 option을 반환 |
static int | showOptionDialog(Component parentComponent, Object message, String title, int optionType, int messageType, Icon icon, Object[] options, Object initialValue) options에 따른 대화상자 선택된 option을 반환 |
static Object static String | showInputDialog(Component parentComponent, Object message, String title, int optionType, int messageType, Icon icon, Object[] selectionValues, Object initialSelectionValue) selectionValues에 따른 대화상자, 선택된 Object를 반환 showInputDialog(Object message, Object initialSelectionValue) 사용자 입력을 요구하는 대화상자, 입력된 문자열을 반환 |
// DialogDemo.java
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class DialogDemo {
public static void main(String s[]) {
JFrame frame = new JFrame("TopLevelDemo");
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.setVisible(true);
JOptionPane.showMessageDialog(null, "alert", "ALERT", JOptionPane.ERROR_MESSAGE);
//Show an information panel with the options yes/no and message 'choose one':
JOptionPane.showConfirmDialog(null, "choose one", "CHOOSE ONE", JOptionPane.YES_NO_OPTION);
//Show a warning dialog with the options OK, CANCEL, title 'Warning', and message 'Click OK to continue':
Object[] options = { "OK", "CANCEL" };
JOptionPane.showOptionDialog(null, "Click OK to continue", "Warning",
JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE,
null, options, options[0]);
//Show a dialog asking the user to type in a String:
String inputValue = JOptionPane.showInputDialog("Please input a value");
System.out.println(inputValue);
//Show a dialog asking the user to select a String:
Object[] possibleValues = { "First", "Second", "Third" };
Object selectedValue = JOptionPane.showInputDialog(null,
"Choose one", "Input",
JOptionPane.INFORMATION_MESSAGE, null,
possibleValues, possibleValues[0]);
System.out.println(selectedValue);
/*
*/
}
}
2)JDialog
java.awt.Container
|
+--java.awt.Window
|
+--java.awt.Dialog
|
+--javax.swing.JDialog
11.2.4애플릿
java.awt.Container
|
+--java.awt.Panel
|
+--java.applet.Applet
|
+--javax.swing.JApplet
이후 애플릿 장에서 설명
11.3레이아웃 관리자
11.3.1개요
레이아웃 관리자는 LayoutManager 인터페이스를 구현한 클래스의 객체를 말한다. 모든 컨테이너는 각각의 기본 레이아웃 관리자를 갖는다. 필요에 따라 기본 레이아웃 관리자를 바꿀 수 있다.
레이아웃 관리자의 종류는 아래와 같다
BorderLayout : 모든 내용창의 기본 레이아웃 관리자다
BoxLayout
CardLayout
FlowLayout : JPanel의 기본 레이아웃 관리자다
GridLayout
GridBagLayout
11.3.2사용법
변경하고자하는 레이아웃 관리자 객체를 생성하고, 변경하려는 컨테이너 객체를 이용하여 생성된 레이아웃 관리자 객체로 레이아웃을 설정하면 된다.
frame.getContentPane().setLayout(new FlowLayout());
컨테이너의 모양이 변하면 자동으로 레이아웃 관리자가 호출된다. 컴포넌트의 모델이 변경하여 자동으로 갱신되지 않는다면 컴포넌트에 대해 직접 revalidate() 메서드를 호출한 후 repaint() 메서드를 호출해야 한다.
BorderLayout
BorderLayout은 중앙, 동, 서, 남, 북 다섯 개의 영역이 있다.
내용창은 기본으로 BorderLayout 이므로 아래와 같이 이용할 수 있다.
public void Container.add(Component comp, Object constraints)
frame.getContentPane().add(new JButton("북“), BorderLayout.NORTH);
BorderLayout.CENTER
BorderLayout.NORTH
BorderLayout.SOUTH
BorderLayout.EAST
BorderLayout.WEST
만약 BorderLayout.CENTER에만 컴포넌트가 있다면 전체를 채운다.
기본으로 각 영역의 크기는 영역에 추가된 컴포넌트의 크기로 결정된다. 또한, 추가할 컴포넌트의 setPreferredSize()를 이용하여 각 영역의 선호하는 크기를 지정할 수 있다.
/*
* Swing version.
*/
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class BorderWindow extends JFrame {
boolean inAnApplet = true;
public BorderWindow() {
Container contentPane = getContentPane();
//Use the content pane's default BorderLayout.
//contentPane.setLayout(new BorderLayout()); //unnecessary
JButton north = new JButton("Button 1 (NORTH)");
north.setPreferredSize(new Dimension(0, 18)); // 0은 의미 없음
JButton west = new JButton("Button 3 (WEST)");
west.setPreferredSize(new Dimension(20, 0));
contentPane.add(north, BorderLayout.NORTH);
contentPane.add(new JButton("2 (CENTER)"), BorderLayout.CENTER);
contentPane.add(west, BorderLayout.WEST);
contentPane.add(new JButton("Long-Named Button 4 (SOUTH)"), BorderLayout.SOUTH);
contentPane.add(new JButton("Button 5 (EAST)"), BorderLayout.EAST);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
if (inAnApplet) {
dispose();
} else {
System.exit(0);
}
}
});
}
public static void main(String args[]) {
BorderWindow window = new BorderWindow();
window.inAnApplet = false;
window.setTitle("BorderLayout");
window.pack();
window.setVisible(true);
}
}
BoxLayout
BoxLayout은 가로나 세로로 컴포넌트를 하나씩 더해간다.
생성자는 아래와 같다.
BoxLayout(Container target, int axis)
target : 레이아웃이 필요한 컨테이너
axis : BoxLayout.X_AXIS, BoxLayout.Y_AXIS
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class BoxWindow extends JFrame {
boolean inAnApplet = true;
public BoxWindow() {
Container contentPane = getContentPane();
contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS));
// contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.X_AXIS));
addAButton("Button 1", contentPane);
addAButton("2", contentPane);
addAButton("Button 3", contentPane);
addAButton("Long-Named Button 4", contentPane);
addAButton("Button 5", contentPane);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
if (inAnApplet) {
dispose();
} else {
System.exit(0);
}
}
});
}
private void addAButton(String text, Container container) {
JButton button = new JButton(text);
button.setAlignmentX(Component.CENTER_ALIGNMENT);
// button.setAlignmentX(Component.LEFT_ALIGNMENT);
// button.setAlignmentX(Component.BOTTOM_ALIGNMENT);
container.add(button);
}
public static void main(String args[]) {
BoxWindow window = new BoxWindow();
window.inAnApplet = false;
window.setTitle("BoxLayout");
window.pack();
window.setVisible(true);
}
}
기타기능
CardLayout
CardLayout은 둘 이상의 컴포넌트들이 같은 공간에 하나씩 보이도록 한다. 여러 카드를 쌓아놓고 한 장씩 보는 것과 같다.
CardLayout을 사용하는 컨테이너에 컴포넌트를 추가할 때는 아래와 같이 컴포넌트를 구분하는데 사용되는 문자열을 포함해야 한다.
public void Container.add(Component comp, Object constraints);
constraints : 컴포넌트를 구분하는 문자열
아래는 CardLayout 클래스의 주요 메서드다.
자료형 | 메서드 / 설명 |
생성자 | |
| CardLayout() |
자료형 | 메서드 / 설명 |
기타 | |
void void void void void | first(Container parent) last(Container parent) previous(Container parent) next(Container parent) show(Container parent, String name) parent : CardLayout을 갖는 컨테이너 name : 보여질 컴포넌트 이름 |
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class CardWindow extends JFrame
implements ItemListener {
boolean inAnApplet = true;
JPanel cards;
final static String BUTTONPANEL = "JPanel with JButtons";
final static String TEXTPANEL = "JPanel with JTextField";
public CardWindow() {
Container contentPane = getContentPane();
//Put the JComboBox in a JPanel to get a nicer look.
String comboBoxItems[] = { BUTTONPANEL, TEXTPANEL };
JPanel cbp = new JPanel();
JComboBox c = new JComboBox(comboBoxItems);
c.setEditable(false);
c.addItemListener(this);
cbp.add(c);
//Use the default layout manager, BorderLayout
contentPane.add(cbp, BorderLayout.NORTH);
cards = new JPanel();
cards.setLayout(new CardLayout());
JPanel p1 = new JPanel();
p1.add(new JButton("Button 1"));
p1.add(new JButton("Button 2"));
p1.add(new JButton("Button 3"));
JPanel p2 = new JPanel();
p2.add(new JTextField("TextField", 20));
cards.add(p1, BUTTONPANEL);
cards.add(p2, TEXTPANEL);
contentPane.add(cards, BorderLayout.CENTER);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
if (inAnApplet) {
dispose();
} else {
System.exit(0);
}
}
});
}
public void itemStateChanged(ItemEvent evt) {
CardLayout cl = (CardLayout)(cards.getLayout());
cl.show(cards, (String)evt.getItem());
}
public static void main(String args[]) {
CardWindow window = new CardWindow();
window.inAnApplet = false;
window.setTitle("CardLayout");
window.pack();
window.setVisible(true);
}
}
FlowLayout
JPanel의 기본 레이아웃 관리자다
FlowLayout은 가로로 컴포넌트를 배치하고 컨테이너의 크기를 넘어서면 다음 줄에 배치한다.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class FlowWindow extends JFrame {
boolean inAnApplet = true;
public FlowWindow() {
Container contentPane = getContentPane();
contentPane.setLayout(new FlowLayout());
contentPane.add(new JButton("Button 1"));
contentPane.add(new JButton("2"));
contentPane.add(new JButton("Button 3"));
contentPane.add(new JButton("Long-Named Button 4"));
contentPane.add(new JButton("Button 5"));
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
if (inAnApplet) {
dispose();
} else {
System.exit(0);
}
}
});
}
public static void main(String args[]) {
FlowWindow window = new FlowWindow();
window.inAnApplet = false;
window.setTitle("FlowLayout");
window.pack();
window.setVisible(true);
}
}
GridLayout
컴포넌트를 셀들로 이루어진 격자에 배치한다. 컴포넌트는 셀의 공간을 전부 차지하고, 모든 셀은 같은 크기다.
아래는 GridLayout 클래스의 주요 메서드다.
자료형 | 메서드 / 설명 |
생성자 | |
| GridLayout(int rows, int cols) rows : 행 셀 개수, 0는 무제한 cols : 열 셀 개수, 0는 무제한 |
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class GridWindow extends JFrame {
boolean inAnApplet = true;
public GridWindow() {
Container contentPane = getContentPane();
contentPane.setLayout(new GridLayout(0,2));
contentPane.add(new JButton("Button 1"));
contentPane.add(new JButton("2"));
contentPane.add(new JButton("Button 3"));
contentPane.add(new JButton("Long-Named Button 4"));
contentPane.add(new JButton("Button 5"));
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
if (inAnApplet) {
dispose();
} else {
System.exit(0);
}
}
});
}
public static void main(String args[]) {
GridWindow window = new GridWindow();
window.inAnApplet = false;
window.setTitle("GridLayout");
window.pack();
window.setVisible(true);
}
}
GridBagLayout
IDE를 통한 GUI 설계
11.3.3커스텀 레이아웃
레이아웃 매니저를 사용하지 않고 직접 픽셀 단위로 컴포넌트의 위치를 지정한다.
Container contentPane = getContentPane();
contentPane.setLayout(null);
Component.setBounds(Rectangle);
// NoLayout.java
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class NoLayout extends JFrame {
private JButton b1, b2, b3;
public NoLayout() {
Container contentPane = getContentPane();
contentPane.setLayout(null);
b1 = new JButton("one");
contentPane.add(b1);
b2 = new JButton("two");
contentPane.add(b2);
b3 = new JButton("three");
contentPane.add(b3);
Insets insets = contentPane.getInsets();
b1.setBounds(25 + insets.left, 5 + insets.top, 75, 20);
b2.setBounds(55 + insets.left, 35 + insets.top, 75, 20);
b3.setBounds(150 + insets.left, 15 + insets.top, 75, 30);
}
public static void main(String[] args) {
JFrame frame = new NoLayout();
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
// frame.pack(); Layout Manager를 사용하지 않으므로 적정 크기를 계산 못함
frame.setSize(new Dimension(300, 200));
frame.setVisible(true);
}
}
읽기전용 속성을 디렉토리 단위로 제거
attrib -r *.* /s
11.4중간 단계 컨테이너
11.4.1패널(JPanel)
javax.swing.JComponent
|
+--javax.swing.JPanel
패널은 레이아웃을 쉽게할 목적으로 컴포넌트들을 그룹화 시킬 때 사용한다. 패널의 기본 레이아웃은 FlowLayout이다. 프로그램에 사용될 컴포넌트들을 여러 그룹으로 나누고 각 그룹을 패널에 넣는다. 또한, 여러 패널을 하나의 패널로 관리할 수 있다.
CardLayout 예에서처럼 내용창을 패널들로 구성하고 각 패널에 여러 컴포넌트를 배치할 수 있다.
아래는 JPanel 클래스의 주요 메서드다.
자료형 | 메서드 / 설명 |
생성자 | |
| JPanel() 더블버퍼링 기본 JPanel(boolean isDoubleBuffered) JPanel(LayoutManager layout) |
자료형 | 메서드 / 설명 |
기타 | |
Component void | Container.add(Component comp) Container.setLayout(LayoutManager layout) |
패널은 컴포넌트를 추가, 삭제하거나 레이아웃을 설정할 때 JComponent의 메서드를 그대로 사용한다.
아래는 CardLayout 예를 수정하여 패널의 구성을 보여준다.
/*
CardPanel.java
*/
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class CardPanel extends JFrame
implements ItemListener {
boolean inAnApplet = true;
JPanel cards;
final static String BUTTONPANEL = "JPanel with JButtons";
final static String TEXTPANEL = "JPanel with JTextField";
public CardPanel() {
Container contentPane = getContentPane();
//Put the JComboBox in a JPanel to get a nicer look.
String comboBoxItems[] = { BUTTONPANEL, TEXTPANEL };
JPanel cbp = new JPanel();
cbp.setBackground(Color.cyan);
JComboBox c = new JComboBox(comboBoxItems);
c.setEditable(false);
c.addItemListener(this);
cbp.add(c);
//Use the default layout manager, BorderLayout
contentPane.add(cbp, BorderLayout.NORTH);
cards = new JPanel();
cards.setBackground(Color.orange);
cards.setLayout(new CardLayout());
JPanel p1 = new JPanel();
// p1.setOpaque(false); //투명하게 하면 cards의 배경이 보인다
p1.setBackground(Color.magenta);
p1.add(new JButton("Button 1"));
p1.add(new JButton("Button 2"));
p1.add(new JButton("Button 3"));
JPanel p2 = new JPanel();
p2.setBackground(Color.pink);
p2.add(new JTextField("TextField", 20));
cards.add(p1, BUTTONPANEL);
cards.add(p2, TEXTPANEL);
contentPane.add(cards, BorderLayout.CENTER);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
if (inAnApplet) {
dispose();
} else {
System.exit(0);
}
}
});
}
public void itemStateChanged(ItemEvent evt) {
CardLayout cl = (CardLayout)(cards.getLayout());
cl.show(cards, (String)evt.getItem());
}
public static void main(String args[]) {
CardPanel window = new CardPanel();
window.inAnApplet = false;
window.setTitle("CardLayout");
window.pack();
window.setVisible(true);
}
}
GUI 연습
1. 성적입력
2. 채팅 창
* 각 컴포넌트 생성 및 변경의 도움말 참조
11.4.2스크롤창(JScrollPane)
컴포넌트가 컨테이너의 크기보다 크거나 가변적인 크기를 갖을 때 스크롤창을 사용한다.
아래는 JScrollPane 클래스의 주요 메서드다.
자료형 | 메서드 / 설명 |
생성자 | |
| JScrollPane(Component view) JScrollPane(Component view, int vsbPolicy, int hsbPolicy) view : 스크롤창의 보임창(viewport)에서 보여질 컴포넌트 vsbPolicy : JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED(기본) , JScrollPane.VERTICAL_SCROLLBAR_NEVER , JScrollPane.VERTICAL_SCROLLBAR_ALWAYS hsbPolicy : JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED(기본) , JScrollPane.HORIZONTAL_SCROLLBAR_NEVER , JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS |
자료형 | 메서드 / 설명 |
기타 | |
void void void | setColumnHeader(JViewport columnHeader) setRowHeader(JViewport rowHeader) setCorner(String key, Component corner) key : JScrollPane.LOWER_LEFT_CORNER JScrollPane.LOWER_RIGHT_CORNER JScrollPane.UPPER_LEFT_CORNER JScrollPane.UPPER_RIGHT_CORNER |
/*
ScrollPaneDemo.java
*/
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.JScrollPane;
import javax.swing.JPanel;
import java.awt.*;
import java.awt.event.*;
public class ScrollPaneDemo extends JFrame {
protected JTextArea textArea;
protected String newline = "\n";
public ScrollPaneDemo() {
//Do frame stuff.
super("ScrollPaneDemo");
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
//Create the text area used for output.
textArea = new JTextArea(5, 10);
for(int i=0; i<10; i++)
textArea.append("반갑습니다. 스크롤패인 연습입니다.\n")
;
JScrollPane scrollPane = new JScrollPane(textArea);
//Lay out the content pane.
JPanel contentPane = new JPanel();
contentPane.setLayout(new BorderLayout());
contentPane.add(scrollPane, BorderLayout.CENTER);
setContentPane(contentPane);
}
public static void main(String[] args) {
ScrollPaneDemo frame = new ScrollPaneDemo();
frame.pack();
frame.setVisible(true);
}
}
11.4.3스플릿창(JSplitPane)
스플릿창은 두 개의 컴포넌트를 상하나 좌우로 나란히 보여준다. 분리바를 조정하여 두 컴포넌트의 영역을 조정할 수 있다.
아래는 JSplitPane 클래스의 주요 메서드다.
자료형 | 메서드 / 설명 |
생성자 | |
| JSplitPane() JSplitPane(int newOrientation, Component newLeftComponent, Component newRightComponent) orientation : JSplitPane.HORIZONTAL_SPLIT(기본값) JSplitPane.VERTICAL_SPLIT newLeftComponent : Top/Left 컴포넌트 newRightComponent : Bottom/Right 컴포넌트 |
자료형 | 메서드 / 설명 |
기타 | |
void void void void void | setOrientation(int orientation) setOneTouchExpandable(boolean newValue) 스플릿창 분리바위에 확장/숨김 화살표시 여부 설정 setDividerSize(int pixel) setDividerLocation(double percent) setDividerLocation(int pixel) |
ResourceBundle
ResourceBundle은 Properties와 비슷한 용도로 사용된다.
아래는 ResourceBundle 클래스의 주요 메서드다.
자료형 | 메서드 / 설명 |
기타 | |
static ResourceBundle String | getBundle(String baseName) baseName : 파일명이 baseName + ".properties" baseName + ".properties" 파일로부터 ResourceBundle 객체생성 getString(String key) ResourceBundle 객체로부터 key에 해당하는 값을 반환 |
"imagenames.properties"의 내용 예
images=Bird.gif Cat.gif Dog.gif Rabbit.gif Pig.gif
/*
SplitPaneDemo.java
*/
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.util.*;
//SplitPaneDemo itself is not a visible component.
public class SplitPaneDemo implements ListSelectionListener {
private Vector imageNames;
private JLabel picture;
private JList list;
private JSplitPane splitPane;
public SplitPaneDemo() {
//Read image names from a properties file
ResourceBundle imageResource;
try {
imageResource = ResourceBundle.getBundle("imagenames");
String imageNamesString = imageResource.getString("images");
imageNames = parseList(imageNamesString);
} catch (MissingResourceException e) {
System.err.println();
System.err.println("Can't find the properties file " +
"that contains the image names.");
System.err.println("Its name should be imagenames.properties, " +
"and it should");
System.err.println("contain a single line that specifies " +
"one or more image");
System.err.println("files to be found in a directory " +
"named images. Example:");
System.err.println();
System.err.println(" images=Bird.gif Cat.gif Dog.gif");
System.err.println();
System.exit(1);
}
//Create the list of images and put it in a scroll pane
list = new JList(imageNames);
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
list.setSelectedIndex(0);
list.addListSelectionListener(this);
JScrollPane listScrollPane = new JScrollPane(list);
//Set up the picture label and put it in a scroll pane
ImageIcon firstImage = new ImageIcon("images/" +
(String)imageNames.firstElement());
picture = new JLabel(firstImage);
picture.setPreferredSize(new Dimension(firstImage.getIconWidth(),
firstImage.getIconHeight()));
JScrollPane pictureScrollPane = new JScrollPane(picture);
//Create a split pane with the two scroll panes in it
splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
listScrollPane, pictureScrollPane);
splitPane.setOneTouchExpandable(true);
splitPane.setDividerLocation(150);
//Provide minimum sizes for the two components in the split pane
Dimension minimumSize = new Dimension(100, 50);
listScrollPane.setMinimumSize(minimumSize);
pictureScrollPane.setMinimumSize(minimumSize);
//Provide a preferred size for the split pane
splitPane.setPreferredSize(new Dimension(400, 200));
}
//Used by SplitPaneDemo2
public JList getImageList() {
return list;
}
public JSplitPane getSplitPane() {
return splitPane;
}
public void valueChanged(ListSelectionEvent e) {
if (e.getValueIsAdjusting())
return;
JList theList = (JList)e.getSource();
if (theList.isSelectionEmpty()) {
picture.setIcon(null);
} else {
int index = theList.getSelectedIndex();
ImageIcon newImage = new ImageIcon("images/" +
(String)imageNames.elementAt(index));
picture.setIcon(newImage);
picture.setPreferredSize(new Dimension(newImage.getIconWidth(),
newImage.getIconHeight() ));
picture.revalidate();
}
}
protected static Vector parseList(String theStringList) {
Vector v = new Vector(10);
StringTokenizer tokenizer = new StringTokenizer(theStringList, " ");
while (tokenizer.hasMoreTokens()) {
String image = tokenizer.nextToken();
v.addElement(image);
}
return v;
}
public static void main(String s[]) {
JFrame frame = new JFrame("SplitPaneDemo");
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {System.exit(0);}
});
SplitPaneDemo splitPaneDemo = new SplitPaneDemo();
frame.getContentPane().add(splitPaneDemo.getSplitPane());
frame.pack();
frame.setVisible(true);
}
}
11.4.4탭창(JTabbedPane)
탭창은 같은 형태의 여러 컴포넌트들을 동일한 공간에 하나씩 보이게 하는데 사용한다. CardLayout과 비슷한 효과를 나타낸다.
아래는 JTabbedPane 클래스의 주요 메서드다.
자료형 | 메서드 / 설명 |
생성자 | |
| JTabbedPane() JTabbedPane(int tabPlacement) tabPlacement : SwingConstants.TOP SwingConstants.BOTTOM SwingConstants.LEFT SwingConstants.RIGHT |
자료형 | 메서드 / 설명 |
기타 | |
void void void Component int void | addTab(String title, Component component) addTab(String title, Icon icon, Component component) addTab(String title, Icon icon, Component component, String tip) getSelectedComponent() getSelectedIndex() setSelectedIndex(int index) |
/*
TabbedPaneDemo.java
*/
import javax.swing.JTabbedPane;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JFrame;
import java.awt.*;
import java.awt.event.*;
public class TabbedPaneDemo extends JPanel {
public TabbedPaneDemo() {
ImageIcon icon = new ImageIcon("images/middle.gif");
JTabbedPane tabbedPane = new JTabbedPane();
Component panel1 = makeTextPanel("Blah");
tabbedPane.addTab("One", icon, panel1, "Does nothing");
tabbedPane.setSelectedIndex(0);
Component panel2 = makeTextPanel("Blah blah");
tabbedPane.addTab("Two", icon, panel2, "Does twice as much nothing");
Component panel3 = makeTextPanel("Blah blah blah");
tabbedPane.addTab("Three", icon, panel3, "Still does nothing");
Component panel4 = makeTextPanel("Blah blah blah blah");
tabbedPane.addTab("Four", icon, panel4, "Does nothing at all");
//Add the tabbed pane to this panel.
setLayout(new GridLayout(1, 1));
add(tabbedPane);
}
protected Component makeTextPanel(String text) {
JPanel panel = new JPanel(false);
JLabel filler = new JLabel(text);
filler.setHorizontalAlignment(JLabel.CENTER);
panel.setLayout(new GridLayout(1, 1));
panel.add(filler);
return panel;
}
public static void main(String[] args) {
JFrame frame = new JFrame("TabbedPaneDemo");
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {System.exit(0);}
});
frame.getContentPane().add(new TabbedPaneDemo(),
BorderLayout.CENTER);
frame.setSize(400, 125);
frame.setVisible(true);
}
}
11.4.5툴바(JToolBar)
툴바는 주로 메뉴 항목들에 해당하는 아이콘화된 버튼들을 한 줄로 그룹화한다. BoxLayout을 기본으로 사용한다. 메뉴 항목과의 연결은 메뉴에서 설명한다.
아래는 JToolBar 클래스의 주요 메서드다.
자료형 | 메서드 / 설명 |
생성자 | |
| JToolBar() JToolBar(int orientation) orientation : SwingConstants.HORIZONTAL SwingConstants.VERTICAL |
자료형 | 메서드 / 설명 |
기타 | |
Component void void | Container.add(Component comp) addSeparator() setFloatable(boolean aFlag) aFlag : true이면 툴바를 드래그하여 컨테이너내의 상하좌우나(컨테이너의 레이아웃이 BorderLayout일 경우) 컨테이너 밖으로 이동할 수 있다. |
import javax.swing.JToolBar;
import javax.swing.JButton;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JTextArea;
/*
ToolBarDemo.java
*/
import javax.swing.JScrollPane;
import javax.swing.JPanel;
import java.awt.*;
import java.awt.event.*;
public class ToolBarDemo extends JFrame {
protected JTextArea textArea;
protected String newline = "\n";
public ToolBarDemo() {
//Do frame stuff.
super("ToolBarDemo");
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
//Create the toolbar.
JToolBar toolBar = new JToolBar();
addButtons(toolBar);
//Create the text area used for output.
textArea = new JTextArea(5, 30);
JScrollPane scrollPane = new JScrollPane(textArea);
//Lay out the content pane.
JPanel contentPane = new JPanel();
contentPane.setLayout(new BorderLayout());
contentPane.setPreferredSize(new Dimension(400, 100));
contentPane.add(toolBar, BorderLayout.NORTH);
contentPane.add(scrollPane, BorderLayout.CENTER);
setContentPane(contentPane);
}
protected void addButtons(JToolBar toolBar) {
JButton button = null;
//first button
button = new JButton(new ImageIcon("images/left.gif"));
button.setToolTipText("This is the left button");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
displayResult("Action for first button");
}
});
toolBar.add(button);
//second button
button = new JButton(new ImageIcon("images/middle.gif"));
button.setToolTipText("This is the middle button");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
displayResult("Action for second button");
}
});
toolBar.add(button);
//third button
button = new JButton(new ImageIcon("images/right.gif"));
button.setToolTipText("This is the right button");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
displayResult("Action for third button");
}
});
toolBar.add(button);
}
protected void displayResult(String actionDescription) {
textArea.append(actionDescription + newline);
}
public static void main(String[] args) {
ToolBarDemo frame = new ToolBarDemo();
frame.pack();
frame.setVisible(true);
}
}
11.4.6내부 프레임(JInternalFrame)
내부 프레임의 컨테이너는 다층창(특히 JDesktopPane)만 가능하다. JDesktopPane은 다층창에 내부 프레임을 위한 API가 추가된 클래스다. 보통 JFrame은 JDesktopPane을 내용창으로 사용하고, JDesktopPane에 내부 프레임들이 추가된다.
javax.swing.JLayeredPane
|
+--javax.swing.JDesktopPane
아래는 JDesktopPane 클래스의 주요 메서드다.
자료형 | 메서드 / 설명 |
생성자 | |
| JDesktopPane() |
자료형 | 메서드 / 설명 |
기타 | |
Component | Container.add(Component comp) |
내부 프렘임은 프레임과 생성 및 설정 메서드가 비슷하지만 최상위 컨테이너가 아니고, 윈도우 이벤트가 아닌 내부 프레임 이벤트를 발생시킨다.
아래는 내부 프레임을 사용할 때 주의할 사항이다.
1)크기를 명시적으로 설정. pack(), setSize(), setBounds()
2)위치 설정
3)컴포넌트는 내부 프레임의 내용창에 추가
4)대화상자는 JOptionPane사용
5)내부 프레임은 JDesktopPane과 같은 컨테이너에 추가
6)show()나 setVisible(true)를 호출
7)내부 프렘임 이벤트 발생
아래는 JInternalFrame 클래스의 주요 메서드다.
자료형 | 메서드 / 설명 |
생성자 | |
| JInternalFrame() JInternalFrame(String title, boolean resizable, boolean closable, boolean maximizable, boolean iconifiable) |
자료형 | 메서드 / 설명 |
기타 | |
Component void void void void | Container.add(Component comp) pack() Component.setBounds(Rectangle bounds) Component.setSize(Dimension size) 크기를 명시하지 않으면 화면에 보이지 않음 Component.setLocation(Point) 위치를 명시하지 않으면 컨테이너의 좌측상단(0, 0)에 위치 |
/*
MyInternalFrame.java
*/
import javax.swing.JInternalFrame;
import java.awt.event.*;
import java.awt.*;
public class MyInternalFrame extends JInternalFrame {
static int openFrameCount = 0;
static final int xOffset = 30, yOffset = 30;
public MyInternalFrame() {
super("Document #" + (++openFrameCount),
true, //resizable
true, //closable
true, //maximizable
true);//iconifiable
//...Create the GUI and put it in the window...
//...Then set the window size or call pack...
setSize(200,100);
//Set the window's location.
setLocation(xOffset*openFrameCount, yOffset*openFrameCount);
}
}
/*
InternalFrameDemo.java
*/
import javax.swing.JInternalFrame;
import javax.swing.JDesktopPane;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JMenuBar;
import javax.swing.JFrame;
import java.awt.event.*;
import java.awt.*;
public class InternalFrameDemo extends JFrame {
JDesktopPane desktop;
public InternalFrameDemo() {
super("InternalFrameDemo");
//Make the big window be indented 50 pixels from each edge
//of the screen.
int inset = 50;
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
setBounds(inset, inset,
screenSize.width / 3,
screenSize.height / 3);
//Quit this app when the big window closes.
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
//Set up the GUI.
desktop = new JDesktopPane(); //a specialized layered pane
createFrame(); //Create first window
setContentPane(desktop);
setJMenuBar(createMenuBar());
//Make dragging faster:
desktop.putClientProperty("JDesktopPane.dragMode", "outline");
}
protected JMenuBar createMenuBar() {
JMenuBar menuBar = new JMenuBar();
JMenu menu = new JMenu("Document");
menu.setMnemonic(KeyEvent.VK_D);
JMenuItem menuItem = new JMenuItem("New");
menuItem.setMnemonic(KeyEvent.VK_N);
menuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
createFrame();
}
});
menu.add(menuItem);
menuBar.add(menu);
return menuBar;
}
protected void createFrame() {
MyInternalFrame frame = new MyInternalFrame();
frame.setVisible(true); //necessary as of kestrel
desktop.add(frame);
try {
frame.setSelected(true);
} catch (java.beans.PropertyVetoException e) {}
}
public static void main(String[] args) {
InternalFrameDemo frame = new InternalFrameDemo();
frame.setVisible(true);
}
}
11.4.7루트창
루트창은 네 개의 요소를 갖는다.
투명창, 다층창, 내용창, 메뉴바
11.4.7.1투명창(GlassPane)
투명창은 루트창에 대한 입력 이벤트를 가로채거나 그 영역위에 무언가를 그릴 때 사용한다.
// GlassPaneDemo
import javax.swing.*;
import javax.swing.event.MouseInputAdapter;
import java.awt.*;
import java.awt.event.*;
public class GlassPaneDemo {
static private MyGlassPane myGlassPane;
public static void main(String[] args) {
JFrame frame = new JFrame("GlassPaneDemo");
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
JCheckBox changeButton =
new JCheckBox("Glass pane \"visible\"");
changeButton.setSelected(false);
changeButton.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
myGlassPane.setVisible(e.getStateChange()
== ItemEvent.SELECTED);
}
});
//Set up the content pane, where the "main GUI" lives.
Container contentPane = frame.getContentPane();
contentPane.setLayout(new FlowLayout());
contentPane.add(changeButton);
contentPane.add(new JButton("Button 1"));
contentPane.add(new JButton("Button 2"));
//Set up the menu bar, which appears above the content pane.
JMenuBar menuBar = new JMenuBar();
JMenu menu = new JMenu("Menu");
menu.add(new JMenuItem("Do nothing"));
menuBar.add(menu);
frame.setJMenuBar(menuBar);
//Set up the glass pane, which appears over both menu bar
//and content pane.
myGlassPane = new MyGlassPane(changeButton, menuBar,
frame.getContentPane());
frame.setGlassPane(myGlassPane);
frame.pack();
frame.setVisible(true);
}
}
/**
* We have to provide our own glass pane so that it can paint.
*/
class MyGlassPane extends JComponent {
Point point;
public void paint(Graphics g) {
if (point != null) {
g.setColor(Color.red);
g.fillOval(point.x - 10, point.y - 10, 20, 20);
}
}
public void setPoint(Point p) {
point = p;
}
public MyGlassPane(AbstractButton aButton,
JMenuBar menuBar,
Container contentPane) {
CBListener listener = new CBListener(aButton, menuBar,
this, contentPane);
addMouseListener(listener);
addMouseMotionListener(listener);
}
}
/**
* Listen for all events that our check box is likely to be
* interested in. Redispatch them to the check box.
*/
class CBListener extends MouseInputAdapter {
Toolkit toolkit;
Component liveButton;
JMenuBar menuBar;
MyGlassPane glassPane;
Container contentPane;
boolean inDrag = false;
public CBListener(Component liveButton, JMenuBar menuBar,
MyGlassPane glassPane, Container contentPane) {
toolkit = Toolkit.getDefaultToolkit();
this.liveButton = liveButton;
this.menuBar = menuBar;
this.glassPane = glassPane;
this.contentPane = contentPane;
}
public void mouseMoved(MouseEvent e) {
redispatchMouseEvent(e, false);
}
/*
* We must forward at least the mouse drags that started
* with mouse presses over the check box. Otherwise,
* when the user presses the check box then drags off,
* the check box isn't disarmed -- it keeps its dark
* gray background or whatever its L&F uses to indicate
* that the button is currently being pressed.
*/
public void mouseDragged(MouseEvent e) {
redispatchMouseEvent(e, false);
}
public void mouseClicked(MouseEvent e) {
redispatchMouseEvent(e, false);
}
public void mouseEntered(MouseEvent e) {
redispatchMouseEvent(e, false);
}
public void mouseExited(MouseEvent e) {
redispatchMouseEvent(e, false);
}
public void mousePressed(MouseEvent e) {
redispatchMouseEvent(e, false);
}
public void mouseReleased(MouseEvent e) {
redispatchMouseEvent(e, true);
inDrag = false;
}
private void redispatchMouseEvent(MouseEvent e,
boolean repaint) {
boolean inButton = false;
boolean inMenuBar = false;
Point glassPanePoint = e.getPoint();
Component component = null;
Container container = contentPane;
Point containerPoint = SwingUtilities.convertPoint(
glassPane,
glassPanePoint,
contentPane);
int eventID = e.getID();
if (containerPoint.y < 0) {
inMenuBar = true;
container = menuBar;
containerPoint = SwingUtilities.convertPoint(
glassPane,
glassPanePoint,
menuBar);
testForDrag(eventID);
}
//XXX: If the event is from a component in a popped-up menu,
//XXX: then the container should probably be the menu's
//XXX: JPopupMenu, and containerPoint should be adjusted
//XXX: accordingly.
component = SwingUtilities.getDeepestComponentAt(
container,
containerPoint.x,
containerPoint.y);
if (component == null) {
return;
}
if (component.equals(liveButton)) {
inButton = true;
testForDrag(eventID);
}
if (inMenuBar || inButton || inDrag) {
Point componentPoint = SwingUtilities.convertPoint(
glassPane,
glassPanePoint,
component);
component.dispatchEvent(new MouseEvent(component,
eventID,
e.getWhen(),
e.getModifiers(),
componentPoint.x,
componentPoint.y,
e.getClickCount(),
e.isPopupTrigger()));
}
if (repaint) {
toolkit.beep();
glassPane.setPoint(glassPanePoint);
glassPane.repaint();
}
}
private void testForDrag(int eventID) {
if (eventID == MouseEvent.MOUSE_PRESSED) {
inDrag = true;
}
}
}
11.4.7.2다층창(JLayeredPane)
다층창은 컨테이너에 포함된 컴포넌트의 전후관계(Z-오더)를 설정할 수 있다. 즉, 한 컴포넌트를 다른 컴포넌트 위에 겹쳐 놓을 수 있다.
최상위 컨테이너는 기본으로 루트층에 다층창을 갖는다. 다층창에는 특정한 용도로 쓰이기 위해 정의된 기능층이 존재하고, 일반적으로 이 기능층을 이용한다.
다층창의 기능층
/*
LayeredPaneDemo.java
*/
import javax.swing.*;
import javax.swing.border.*;
import java.awt.*;
import java.awt.event.*;
public class LayeredPaneDemo extends JFrame {
private String[] layerStrings = { "Yellow (0)", "Magenta (1)",
"Cyan (2)", "Red (3)",
"Green (4)" };
private Color[] layerColors = { Color.yellow, Color.magenta,
Color.cyan, Color.red,
Color.green };
private JLayeredPane layeredPane;
private JLabel dukeLabel;
public LayeredPaneDemo() {
super("LayeredPaneDemo");
//Create and load the duke icon.
final ImageIcon icon = new ImageIcon("images/dukeWaveRed.gif");
//Create and set up the layered pane.
layeredPane = new JLayeredPane();
layeredPane.setPreferredSize(new Dimension(300, 310));
layeredPane.setBorder(BorderFactory.createTitledBorder(
"Move the Mouse to Move Duke"));
layeredPane.addMouseMotionListener(new MouseMotionAdapter() {
final int XFUDGE = 40;
final int YFUDGE = 57;
public void mouseEntered(MouseEvent e) {
dukeLabel.setLocation(e.getX()-XFUDGE, e.getY()-YFUDGE);
}
public void mouseMoved(MouseEvent e) {
dukeLabel.setLocation(e.getX()-XFUDGE, e.getY()-YFUDGE);
}
});
//This is the origin of the first label added.
Point origin = new Point(10, 20);
//This is the offset for computing the origin for the next label.
int offset = 35;
//Add several overlapping, colored labels to the layered pane
//using absolute positioning/sizing.
for (int i = 0; i < layerStrings.length; i++) {
JLabel label = createColoredLabel(layerStrings[i],
layerColors[i], origin);
layeredPane.add(label, new Integer(i));
origin.x += offset;
origin.y += offset;
}
//Create and add the Duke label to the layered pane.
dukeLabel = new JLabel(icon);
dukeLabel.setBounds(15, 225,
icon.getIconWidth(),
icon.getIconHeight());
layeredPane.add(dukeLabel, new Integer(2), 0);
//Add control pane and layered pane to frame.
Container contentPane = getContentPane();
contentPane.setLayout(new BoxLayout(contentPane,
BoxLayout.Y_AXIS));
contentPane.add(Box.createRigidArea(new Dimension(0, 10)));
contentPane.add(createControlPanel());
contentPane.add(Box.createRigidArea(new Dimension(0, 10)));
contentPane.add(layeredPane);
}
//Create and set up a colored label.
private JLabel createColoredLabel(String text,
Color color,
Point origin) {
JLabel label = new JLabel(text);
label.setVerticalAlignment(JLabel.TOP);
label.setHorizontalAlignment(JLabel.CENTER);
label.setOpaque(true);
label.setBackground(color);
label.setForeground(Color.black);
label.setBorder(BorderFactory.createLineBorder(Color.black));
label.setBounds(origin.x, origin.y, 140, 140);
return label;
}
//Create the control pane for the top of the frame.
private JPanel createControlPanel() {
final JCheckBox onTop = new JCheckBox("Top Position in Layer");
onTop.setSelected(true);
onTop.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (onTop.isSelected())
layeredPane.moveToFront(dukeLabel);
else
layeredPane.moveToBack(dukeLabel);
}
});
final JComboBox layerList = new JComboBox(layerStrings);
layerList.setSelectedIndex(2); //Cyan layer
layerList.addActionListener(new ActionListener () {
public void actionPerformed(ActionEvent e) {
int position = onTop.isSelected() ? 0 : 1;
layeredPane.setLayer(dukeLabel,
layerList.getSelectedIndex(),
position);
}
});
JPanel controls = new JPanel();
controls.add(layerList);
controls.add(onTop);
controls.setBorder(BorderFactory.createTitledBorder(
"Choose Duke's Layer and Position"));
return controls;
}
public static void main(String[] args) {
JFrame frame = new LayeredPaneDemo();
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.pack();
frame.setVisible(true);
}
}
11.4.7.3메뉴바(JMenuBar)
메뉴바는 메뉴를 관리하는 컴포넌트다.
여러 가지 메뉴가 메뉴바에 추가될 수 있고, 메뉴바는 프레임이나 루트창에 설정될 수 있다.
메뉴를 사용하기 위해서는 메뉴바를 생성하여 애플릿, 다이얼로그, 프레임, 내부프레임, 루트창에 설정한다.
JApplet.setJMenuBar(JMenuBar)
JDialog.setJMenuBar(JMenuBar)
JFrame.setJMenuBar(JMenuBar)
JInternalFrame.setJMenuBar(JMenuBar)
JRootPane.setJMenuBar(JMenuBar)
메뉴를 생성하여 메뉴바에 추가한다.
public JMenu JMenuBar.add(JMenu c);
// MenuLookDemo.java
import java.awt.*;
import java.awt.event.*;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.ButtonGroup;
import javax.swing.JMenuBar;
import javax.swing.KeyStroke;
import javax.swing.ImageIcon;
import javax.swing.JTextArea;
import javax.swing.JScrollPane;
import javax.swing.JFrame;
/*
* This class exists solely to show you what menus look like.
* It has no menu-related event handling.
*/
public class MenuLookDemo extends JFrame {
JTextArea output;
JScrollPane scrollPane;
public MenuLookDemo() {
JMenuBar menuBar;
JMenu menu, submenu;
JMenuItem menuItem;
JCheckBoxMenuItem cbMenuItem;
JRadioButtonMenuItem rbMenuItem;
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
//Add regular components to the window, using the default BorderLayout.
Container contentPane = getContentPane();
output = new JTextArea(5, 30);
output.setEditable(false);
scrollPane = new JScrollPane(output);
contentPane.add(scrollPane, BorderLayout.CENTER);
//Create the menu bar.
menuBar = new JMenuBar();
setJMenuBar(menuBar);
선택된 option을 반환
//Build the first menu.
menu = new JMenu("A Menu");
menu.setMnemonic(KeyEvent.VK_A);
menu.getAccessibleContext().setAccessibleDescription(
"The only menu in this program that has menu items");
menuBar.add(menu);
//a group of JMenuItems
menuItem = new JMenuItem("A text-only menu item",
KeyEvent.VK_T);
//menuItem.setMnemonic(KeyEvent.VK_T); //used constructor instead
menuItem.setAccelerator(KeyStroke.getKeyStroke(
KeyEvent.VK_1, ActionEvent.ALT_MASK));
menuItem.getAccessibleContext().setAccessibleDescription(
"This doesn't really do anything");
menu.add(menuItem);
menuItem = new JMenuItem("Both text and icon",
new ImageIcon("images/middle.gif"));
menuItem.setMnemonic(KeyEvent.VK_B);
menu.add(menuItem);
menuItem = new JMenuItem(new ImageIcon("images/middle.gif"));
menuItem.setMnemonic(KeyEvent.VK_D);
menu.add(menuItem);
//a group of radio button menu items
menu.addSeparator();
ButtonGroup group = new ButtonGroup();
rbMenuItem = new JRadioButtonMenuItem("A radio button menu item");
rbMenuItem.setSelected(true);
rbMenuItem.setMnemonic(KeyEvent.VK_R);
group.add(rbMenuItem);
menu.add(rbMenuItem);
rbMenuItem = new JRadioButtonMenuItem("Another one");
rbMenuItem.setMnemonic(KeyEvent.VK_O);
group.add(rbMenuItem);
menu.add(rbMenuItem);
//a group of check box menu items
menu.addSeparator();
cbMenuItem = new JCheckBoxMenuItem("A check box menu item");
cbMenuItem.setMnemonic(KeyEvent.VK_C);
menu.add(cbMenuItem);
cbMenuItem = new JCheckBoxMenuItem("Another one");
cbMenuItem.setMnemonic(KeyEvent.VK_H);
menu.add(cbMenuItem);
//a submenu
menu.addSeparator();
submenu = new JMenu("A submenu");
submenu.setMnemonic(KeyEvent.VK_S);
menuItem = new JMenuItem("An item in the submenu");
menuItem.setAccelerator(KeyStroke.getKeyStroke(
KeyEvent.VK_2, ActionEvent.ALT_MASK));
submenu.add(menuItem);
menuItem = new JMenuItem("Another item");
submenu.add(menuItem);
menu.add(submenu);
//Build second menu in the menu bar.
menu = new JMenu("Another Menu");
menu.setMnemonic(KeyEvent.VK_N);
menu.getAccessibleContext().setAccessibleDescription(
"This menu does nothing");
menuBar.add(menu);
}
public static void main(String[] args) {
MenuLookDemo window = new MenuLookDemo();
window.setTitle("MenuLookDemo");
window.setSize(450, 260);
window.setVisible(true);
}
}
11.5Event Model
11.5.1Delegation Model
1)용어
이벤트 : 마우스, 키보드 입력 등과 같은 사용자 입력, 기타 시스템 이벤트 등
이벤트 소스 : 이벤트를 발생시키는 컴포넌트
이벤트 종류 : 로우레벨 이벤트, 시멘틱 이벤트
이벤트 타켓 : 이벤트의 처리를 담당하는 클래스의 객체
리스너 구현 또은 아답터 상속
컨테이너, 내부클래스, 익명 내부클래스가 된다
이벤트 리스너 : 이벤트 종류에 따라 수행해야 할 메서드를 선언한 인터페이스
이벤트 아답터 : 이벤트 리스너를 구현한 비어있는 클래스 : {}
이벤트 핸들러 : 이벤트가 발생되면 수행되어야 할 메서드
이벤트 종류에 따라 리스너에 선언됨
이벤트 타겟 클래스에서 구현
이벤트 소스 얻기(getSource(), getActionCommand())
처리 절차 기술
2)이벤트 소스와 종류
로우레벨 이벤트 : 윈도우 시스템에서 발생하거나 사용자 입력에 의해 발생되는 이벤트
윈도우, 마우스, 키보드 등
시멘틱 이벤트 : 로우레벨 이벤트 외의 모든 이벤트
버튼 선택, 메뉴 아이템 선택 등
각 컴포넌트(소스)의 addXXXListener()를 확인하여 XXX에 해당되는 이벤트가 발생 가능함을 알 수 있다.
Component (이벤트 소스) | Listener(이벤트 종류) | |||||||
action | caret | change | document,undoable edit | item | list selection | window | other | |
button | X | X | X | |||||
check box | X | X | X | |||||
color chooser | X | |||||||
combo box | X | X | ||||||
dialog | X | |||||||
editor pane | X | X | hyperlink | |||||
file chooser | X | |||||||
frame | X | |||||||
internal frame | internal frame | |||||||
list | X | list data | ||||||
menu | menu | |||||||
menu item | X | X | X | menu keymenu drag mouse | ||||
option pane | ||||||||
password field | X | X | X | |||||
popup menu | popup menu | |||||||
progress bar | X | |||||||
radio button | X | X | X | |||||
slider | X | |||||||
tabbed pane | X | |||||||
table | X | table modeltable column modelcell editor | ||||||
text area | X | X | ||||||
text field | X | X |
| X | ||||
text pane | X | X | hyperlink | |||||
toggle button | X | X | X | |||||
tree | tree expansiontree will expandtree modeltree selection | |||||||
viewport (used byscrollpane) | X |
'Programming > JAVA' 카테고리의 다른 글
[펌] [SWING]JFileChooser (0) | 2005.06.29 |
---|---|
[펌] 서버 소켓 예제 (0) | 2005.06.24 |
[펌] 클라이언트 소켓 (0) | 2005.06.24 |
[펌] 13. 쓰레드(Thread) (0) | 2005.06.23 |
[펌] 통신을 위한 THREAD 프로그래밍 (0) | 2005.06.23 |