제 9주 이벤트 처리 그래픽프로그래밍1 제 9주 강의 목표 • 버튼, 텍스트필드, 마우스를 통한 입력에 대한 처리 프로그램 작성법을 배움 • 배치관리자를 이해하게 됨 • Nested class, 특히 local 클래스를 사용할 수 있게 됨 객체지향프로그래밍 강원대학교 1 이벤트 처리 객체지향프로그래밍 강원대학교 2 이벤트 (Events) • 이벤트 발생 – 버튼을 클릭할 때 – 텍스트필드에 문자를 타이핑할 때 – 콤보박스에서 아이템을 선택할 때 – 타이머가 타임아웃될 때, 등등... • 버튼, 텍스트필드 등 GUI 콤포넌트들이 이벤트 소 스(source)임 객체지향프로그래밍 강원대학교 3 이벤트 (Events) • 프로그래머는 수많은 이벤트 중 관심 있는 이벤트 에 대해서만 필요한 반응을 보이도록 프로그램을 작성 • 특정 GUI 콤포넌트에서 발생하는 특정 이벤트에 대해 어떤 반응을 보이도록 프로그램하려면 적절 한 이벤트 리스너(listener)를 만들어 이를 해당 콤 포넌트에 등록해 줌 객체지향프로그래밍 강원대학교 4 이벤트 소스와 이벤트 리스너 • Event listener: – 이벤트가 발생될 때 그 사실을 통보받는 객체 – 프로그래머에 의해 작성되는 클래스 객체 – 이벤트가 발생되었을 때 해야 할 작업이 이곳에 정의되 어 있음 – 이벤트 리스너가 등록되지 않은 이벤트에 대해서는 아 무 반응도 없게 됨 • Event source: – 어떤 컴포넌트에서 이벤트가 발생되면 그 컴포넌트에 등록된 모든 이벤트 리스너들에게 이벤트 발생 사실이 통보됨 객체지향프로그래밍 강원대학교 5 이벤트 소스와 이벤트 리스너 • 이벤트가 여러 리스너에게 전달될 수 있다. • 한 리스너가 여러 소스로부터 이벤트를 받을 수 있다. 객체지향프로그래밍 강원대학교 6 예1: ActionListener • 버튼을 클릭하면 action event 발생 (버튼: 이벤트 소스) • 이에 대해 반응을 보이게 하려면 ActionListener 객체를 버튼 에 등록해 줌 (이 때 ActionListener 객체가 이벤트 리스너임) • ActionListener 객체 = ActionListener 인터페이스를 구현한 객체 public interface ActionListener { void actionPerformed(ActionEvent event); } • 이벤트 발생에 따라 ActionListener 객체에게 이벤트 발생이 통보되면 actionPerformed 메소드가 실행됨 객체지향프로그래밍 강원대학교 7 ActionListener 구현 예 import java.awt.event.ActionEvent; import java.awt.event.ActionListener; public class ClickListener implements ActionListener { public void actionPerformed(ActionEvent event) { System.out.println("I was clicked."); } } • ClickListener 객체는 ActionListener 인터페이스를 구현하고 있음 • 모든 ClickListener 객체는 ActionListener임 • ClickListener 객체를 이벤트 리스너로서 버튼에 등록해 주면 버튼 클릭 때마 다 ClickListenr의 actionPerformed 메소드가 실행됨 객체지향프로그래밍 강원대학교 8 File ButtonTester.java public class ButtonViewer { public static void main(String[] args) { JFrame frame = new JFrame(); JButton button = new JButton("Click me!"); frame.add(button); ActionListener listener = new ClickListener(); button.addActionListener(listener); frame.pack(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } } 객체지향프로그래밍 강원대학교 9 Output 객체지향프로그래밍 강원대학교 10 예2 객체지향프로그래밍 강원대학교 11 public class ClickListener implements ActionListener { public void actionPerformed(ActionEvent event) { System.out.println("I was clicked."); } } public class ClickListener implements ActionListener{ ClickListener(JTextField tf){ textField = tf; } public void actionPerformed(ActionEvent event){ textField.setText("I was clicked."); } JTextField textField; } 객체지향프로그래밍 강원대학교 12 public class ButtonViewer{ public static void main(String[] args){ JFrame frame = new JFrame(); JPanel panel = new JPanel(); JButton button = new JButton("Click me!"); final JTextField textField = new JTextField(20); panel.add(button); panel.add(textField); frame.add(panel); ActionListener listener = new ClickListener(textField); button.addActionListener(listener); frame.pack(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } } 객체지향프로그래밍 강원대학교 13 Nested Classes 객체지향프로그래밍 강원대학교 14 Nested Classes • A nested class is a member of its enclosing class • Non-static nested classes (inner classes) have access to other members of the enclosing class, even if they are declared private • Static nested classes do not have access to other members of the enclosing class 객체지향프로그래밍 강원대학교 15 Nested Classes class OuterClass { ... class NestedClass { ... } } A nested class is a member of its enclosing class 객체지향프로그래밍 강원대학교 16 static nested classes, non-static nested classes non-static nested classes are called inner classes class OuterClass { ... static class StaticNestedClass { ... } class InnerClass { ... } } 객체지향프로그래밍 강원대학교 17 Why Use Nested Classes? • It is a way of logically grouping classes that are only used in one place. • It increases encapsulation. • Nested classes can lead to more readable and maintainable code. 객체지향프로그래밍 강원대학교 18 Static Nested Classes • A static nested class cannot refer directly to instance variables or methods defined in its enclosing class — it can use them only through an object reference. • A static nested class is behaviorally a top-level class that has been nested in another. • OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass(); 객체지향프로그래밍 강원대학교 19 Inner Classes • Inner class is associated with an instance of its enclosing class and has direct access to that object's methods and fields Instance of InnerClass class OuterClass { ... class InnerClass { Instance of ... OuterClass } } Objects that are instances of an inner class exist within an instance of the outer class 객체지향프로그래밍 강원대학교 20 Inner Classes • To instantiate an inner class – first instantiate the outer class – create the inner object within the outer object OuterClass outerObject = new OuterClass(); OuterClass.InnerClass innerObject = outerObject.new InnerClass(); 객체지향프로그래밍 강원대학교 21 무엇이 잘 못인가? public class Problem { String s; static class Inner { void testMethod() { s = "Set from Inner"; } } } 객체지향프로그래밍 강원대학교 22 public class Class1 { protected InnerClass1 ic; public Class1() { ic = new InnerClass1(); } public void displayStrings() { System.out.println(ic.getString() + "."); } static public void main(String[] args) { Class1 c1 = new Class1(); c1.displayStrings(); } protected class InnerClass1 { public String getString() { return "InnerClass1: getString invoked"; } } }객체지향프로그래밍 강원대학교 23 Inner Classes Two special kinds of inner classes • local inner classes – 메소드 내부에 선언된 inner class • anonymous inner classes – 이름 없이 메소드 내부에 선언된 inner class 객체지향프로그래밍 강원대학교 24 public class ButtonViewer{ public static void main(String[] args){ JFrame frame = new JFrame(); JButton button = new JButton("Click me!"); frame.add(button); ActionListener listener = new ClickListener(); button.addActionListener(listener); frame.pack(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } } public class ClickListener implements ActionListener{ public void actionPerformed(ActionEvent event){ System.out.println("I was clicked."); } } 객체지향프로그래밍 강원대학교 25 public class ButtonViewer{ public static void main(String[] args){ JFrame frame = new JFrame(); JButton button = new JButton("Click me!"); frame.add(button); class ClickListener implements ActionListener{ public void actionPerformed(ActionEvent event){ System.out.println("I was clicked."); } local inner class } ActionListener listener = new ClickListener(); button.addActionListener(listener); frame.pack(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } } 객체지향프로그래밍 강원대학교 26 Text Field • JTextField final int FIELD_WIDTH = 10; // In characters final JTextField rateField = new JTextField(FIELD_WIDTH); 객체지향프로그래밍 강원대학교 27 public class ButtonViewer{ public static void main(String[] args){ JFrame frame = new JFrame(); JPanel panel = new JPanel(); JButton button = new JButton("Click me!"); final JTextField textField = new JTextField(20); panel.add(button); panel.add(textField); local inner class frame.add(panel); class ClickListener implements ActionListener{ public void actionPerformed(ActionEvent event){ textField.setText("I was clicked."); } } ActionListener listener = new ClickListener(); button.addActionListener(listener); frame.pack(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } } 객체지향프로그래밍 강원대학교 28 public class ButtonViewer{ public static void main(String[] args){ JFrame frame = new JFrame(); JPanel panel = new JPanel(); JButton button = new JButton("Click me!"); final JTextField textField = new JTextField(20); panel.add(button); panel.add(textField); frame.add(panel); class ClickListener implements ActionListener{ public void actionPerformed(ActionEvent event){ textField.setText("I was clicked."); } } ... } } Local class 내에서 그 local class를 포함하고 있는 메소드의 지역변수를 사용하려면 그 지역변수가 final로 선언되어 있어야 한다. 객체지향프로그래밍 강원대학교 29 public class ButtonViewer{ public static void main(String[] args){ JFrame frame = new JFrame(); JPanel panel = new JPanel(); JButton button = new JButton("Click me!"); final JTextField textField = new JTextField(20); panel.add(button); local inner class를 사용 panel.add(textField); 하지 않는 경우와 비교 frame.add(panel); ActionListener listener = new ClickListener(textField); button.addActionListener(listener); frame.pack(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } } 객체지향프로그래밍 강원대학교 30 public class ClickListener implements ActionListener{ ClickListener(JTextField tf){ textField = tf; } public void actionPerformed(ActionEvent event){ textField.setText("I was clicked."); } local inner class를 사용 JTextField textField; 하지 않는 경우와 비교 } 객체지향프로그래밍 강원대학교 31 public class ButtonViewer{ public static void main(String[] args){ JFrame frame = new JFrame(); JPanel panel = new JPanel(); JButton button = new JButton("Click me!"); final JTextField textField = new JTextField(20); panel.add(button); Anonymous inner class panel.add(textField); frame.add(panel); ActionListener listener = new ActionListener() { public void actionPerformed(ActionEvent event){ textField.setText("I was clicked."); } }; button.addActionListener(listener); frame.pack(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } }객체지향프로그래밍 강원대학교 32 예3 • 버튼을 클릭할 때마다 이자가 더해지고 잔액이 화 면에 표시됨 객체지향프로그래밍 강원대학교 33 리스너 구현 class AddInterestListener implements ActionListener { public void actionPerformed(ActionEvent event) { double interest = account.getBalance() * INTEREST_RATE / 100; account.deposit(interest); label.setText("balance=" + account.getBalance()); } } 객체지향프로그래밍 강원대학교 34 File InvestmentViewer1.java 01: 02: 03: 04: 05: 06: 07: 08: 09: 10: 11: 12: 13: 14: 15: 16: 17: import import import import import import import java.awt.event.ActionEvent; java.awt.event.ActionListener; javax.swing.JButton; javax.swing.JFrame; javax.swing.JLabel; javax.swing.JPanel; javax.swing.JTextField; /** This program displays the growth of an investment. */ public class InvestmentViewer1 { public static void main(String[] args) { JFrame frame = new JFrame(); 객체지향프로그래밍 강원대학교 35 File InvestmentViewer1.java 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: // The button to trigger the calculation JButton button = new JButton("Add Interest"); // The application adds interest to this bank account final BankAccount account = new BankAccount(INITIAL_BALANCE); // The label for displaying the results final JLabel label = new JLabel( "balance=" + account.getBalance()); // The panel that holds the user interface components JPanel panel = new JPanel(); panel.add(button); panel.add(label); frame.add(panel); 객체지향프로그래밍 강원대학교 36 File InvestmentViewer1.java 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: class AddInterestListener implements ActionListener { public void actionPerformed(ActionEvent event) { double interest = account.getBalance() * INTEREST_RATE / 100; account.deposit(interest); label.setText( "balance=" + account.getBalance()); } } // inner class 이므로 account, label 사용 가능! ActionListener listener = new AddInterestListener(); button.addActionListener(listener); frame.setSize(FRAME_WIDTH, FRAME_HEIGHT); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } 객체지향프로그래밍 강원대학교 37 File InvestmentViewer1.java 53: 54: 55: 56: 57: 58: 59: } private static final double INTEREST_RATE = 10; private static final double INITIAL_BALANCE = 1000; private static final int FRAME_WIDTH = 400; private static final int FRAME_HEIGHT = 100; 객체지향프로그래밍 강원대학교 38 등록 callback AddInterestListener 객체 actionPerformed() 메소드 객체지향프로그래밍 강원대학교 재계산 및 디스플레이 39 예4 JTextField 객체지향프로그래밍 강원대학교 40 Processing Text Input class AddInterestListener implements ActionListener { public void actionPerformed(ActionEvent event) { double rate = Double.parseDouble(rateField.getText()); . . . } } 객체지향프로그래밍 강원대학교 41 File InvestmentViewer2.java 01: 02: 03: 04: 05: 06: 07: 08: 09: 10: 11: 12: 13: 14: 15: 16: 17: import import import import import import import java.awt.event.ActionEvent; java.awt.event.ActionListener; javax.swing.JButton; javax.swing.JFrame; javax.swing.JLabel; javax.swing.JPanel; javax.swing.JTextField; /** This program displays the growth of an investment. */ public class InvestmentViewer2 { public static void main(String[] args) { JFrame frame = new JFrame(); 객체지향프로그래밍 강원대학교 42 File InvestmentViewer2.java 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: // The label and text field for entering the //interest rate JLabel rateLabel = new JLabel("Interest Rate: "); final int FIELD_WIDTH = 10; final JTextField rateField = new JTextField(FIELD_WIDTH); rateField.setText("" + DEFAULT_RATE); // The button to trigger the calculation JButton button = new JButton("Add Interest"); // The application adds interest to this bank account final BankAccount account = new BankAccount(INITIAL_BALANCE); 30: 31: // The label for displaying the results 32: final JLabel resultLabel = new JLabel( 33: "balance=" + account.getBalance()); 34:객체지향프로그래밍 강원대학교 43 File InvestmentViewer2.java 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: // The panel that holds the user interface components JPanel panel = new JPanel(); panel.add(rateLabel); panel.add(rateField); panel.add(button); panel.add(resultLabel); frame.add(panel); class AddInterestListener implements ActionListener { public void actionPerformed(ActionEvent event) { double rate = Double.parseDouble( rateField.getText()); double interest = account.getBalance() * rate / 100; account.deposit(interest); 객체지향프로그래밍 강원대학교 44 File InvestmentViewer2.java 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: } resultLabel.setText( "balance=" + account.getBalance()); } } ActionListener listener = new AddInterestListener(); button.addActionListener(listener); frame.setSize(FRAME_WIDTH, FRAME_HEIGHT); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } private static final double DEFAULT_RATE = 10; private static final double INITIAL_BALANCE = 1000; private static final int FRAME_WIDTH = 500; private static final int FRAME_HEIGHT = 200; 객체지향프로그래밍 강원대학교 45 배치관리 Layout Management 객체지향프로그래밍 강원대학교 46 배치 관리 Layout Management • 컨테이너는 배치관리자(layout manager)를 갖 는다. • 배치관리자 – border layout – flow layout – grid layout 객체지향프로그래밍 강원대학교 47 Layout Management • JPanel은 기본으로 FlowLayout manager 를 갖는다. • FlowLayout manager는 컴포넌트를 옆으로 차례로 늘어 놓는다. • JPanel이 다른 종류의 layout manager를 사용하도록 할 수도 있다. JPanel panel1 = new Jpanel(); panel.setLayout(new BorderLayout()); 객체지향프로그래밍 강원대학교 48 Border Layout 객체지향프로그래밍 강원대학교 49 Border Layout • • Frame (실제로는 frame의 content pane)의 기본 배치관리자는 BorderLayout 컴포넌트를 넣는 법 JPanel panel1 = new Jpanel(); panel.setLayout(new BorderLayout()); panel.add(component, BorderLayout.NORTH); • 전체 컨테이너 면적을 꽉 채우도록 각 컴포넌트의 크기를 늘여 조절함 객체지향프로그래밍 강원대학교 50 Grid Layout • • 전체 영역을 격자형으로 구획하고 차례로 컴포넌트를 삽 입 컴포넌트들이 같은 크기를 갖도록 크기 조정 JPanel numberPanel = new JPanel(); numberPanel.setLayout(new GridLayout(4, 3)); numberPanel.add(button7); numberPanel.add(button8); numberPanel.add(button9); numberPanel.add(button4); . . . 객체지향프로그래밍 강원대학교 51 Swing Package 교과서 14장을 읽으시오. 객체지향프로그래밍 강원대학교 52 Graphical User Interface (GUI) components Abstract Window Toolkit (AWT) – "heavyweight" components – java.awt.Button – java.awt.Checkbox – java.awt.Dialog Swing - "lightweight" components – javax.swing.JButton – javax.swing.JCheckBox – javax.swing.JDialog 객체지향프로그래밍 강원대학교 53 Swing Components http://download.oracle.com/javase/tutorial/ui/fea tures/components.html 객체지향프로그래밍 강원대학교 54 Swing examples http://java.sun.com/docs/books/tutorial/uis wing/examples/components/index.html#Butt onDemo 객체지향프로그래밍 강원대학교 55 Choices • • • Radio buttons Check boxes Combo boxes 객체지향프로그래밍 강원대학교 56 Radio Buttons • Font sizes are mutually exclusive: JRadioButton smallButton = new JRadioButton("Small"); JRadioButton mediumButton = new JRadioButton("Medium"); JRadioButton largeButton = new JRadioButton("Large"); // Add radio buttons into a ButtonGroup so that // only one button in group is on at any time ButtonGroup group = new ButtonGroup(); group.add(smallButton); group.add(mediumButton); group.add(largeButton); 객체지향프로그래밍 강원대학교 57 Radio Buttons • Button group은 버튼들을 가까이 모아 놓지는 않음, 프로그래머가 알아서 버튼을 배치해야 함 • isSelected: 버튼이 선택됐는지 알아보기 위 해 호출 (largeButton.isSelected()) size = LARGE_SIZE; • setSelected(true) 프레임을 화면이 보이 기 전에 (setVisible(true)) 라디오버튼 하나에게 호출 객체지향프로그래밍 강원대학교 58 Borders (경계선) • 어느 컴포넌트에건 경계선을 넣을 수 있으나 주 로 panel에 사용됨 Jpanel panel = new JPanel (); panel.setBorder(new EtchedBorder ()); Panel.setBorder(new TitledBorder(new EtchedBorder(), “Size”)); 객체지향프로그래밍 강원대학교 59 Borders (경계선) 객체지향프로그래밍 강원대학교 60 Check Boxes JCheckBox italicCheckBox = new JCheckBox("Italic"); 객체지향프로그래밍 강원대학교 61 Combo Boxes • 선택지가 많을 때는 Combo Box를 사용 – 라디오 버튼에 비해 공간을 적게 차지하므로 • "Combo": combination of a list and a text field – The text field displays the name of the current selection 객체지향프로그래밍 강원대학교 62 Combo Boxes • If combo box is editable, user can type own selection – Use setEditable method • Add strings with addItem method: JComboBox facenameCombo = new JComboBox(); facenameCombo.addItem("Serif"); facenameCombo.addItem("SansSerif"); . . . 객체지향프로그래밍 강원대학교 63 Combo Boxes • Get user selection with getSelectedItem (return type is Object) String selectedString = (String) facenameCombo.getSelectedItem(); • Select an item with setSelectedItem 객체지향프로그래밍 강원대학교 64 Radio Buttons, Check Boxes, and Combo Boxes • 이 컴포넌트들은 아이템이 선택될 때 ActionEvent를 발생시킴 객체지향프로그래밍 강원대학교 65 An example: ChoiceFrame 객체지향프로그래밍 강원대학교 66 Classes of the Font Choice Program 객체지향프로그래밍 강원대학교 67 File ChoiceFrameViewer.java 01: 02: 03: 04: 05: 06: 07: 08: 09: 10: 11: 12: 13: 14: 15: import javax.swing.JFrame; /** This program tests the ChoiceFrame. */ public class ChoiceFrameViewer { public static void main(String[] args) { JFrame frame = new ChoiceFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } } 객체지향프로그래밍 강원대학교 68 File ChoiceFrame.java 001: 002: 003: 004: 005: 006: 007: 008: 009: 010: 011: 012: 013: 014: 015: 016: import import import import import import import import import import import import import import import java.awt.BorderLayout; java.awt.Font; java.awt.GridLayout; java.awt.event.ActionEvent; java.awt.event.ActionListener; javax.swing.ButtonGroup; javax.swing.JButton; javax.swing.JCheckBox; javax.swing.JComboBox; javax.swing.JFrame; javax.swing.JLabel; javax.swing.JPanel; javax.swing.JRadioButton; javax.swing.border.EtchedBorder; javax.swing.border.TitledBorder; 객체지향프로그래밍 강원대학교 69 File ChoiceFrame.java 017: 018: 019: 020: 021: 022: 023: 024: 025: 026: 027: 028: 029: 030: 031: /** This frame contains a text field and a control panel to change the font of the text. */ public class ChoiceFrame extends JFrame { /** Constructs the frame. */ public ChoiceFrame() { // Construct text sample sampleField = new JLabel("Big Java"); add(sampleField, BorderLayout.CENTER); 객체지향프로그래밍 강원대학교 70 File ChoiceFrame.java 032: 033: 034: 035: 036: 037: 038: 039: 040: 041: 042: 043: 044: 045: 046: 047: // This listener is shared among all components class ChoiceListener implements ActionListener { public void actionPerformed(ActionEvent event) { setSampleFont(); } } listener = new ChoiceListener(); createControlPanel(); setSampleFont(); setSize(FRAME_WIDTH, FRAME_HEIGHT); } 객체지향프로그래밍 강원대학교 71 File ChoiceFrame.java 048: 049: 050: 051: 052: 053: 054: 055: 056: 057: 058: 059: 060: 061: 062: 063: 064: /** Creates the control panel to change the font. */ public void createControlPanel() { JPanel facenamePanel = createComboBox(); JPanel styleGroupPanel = createCheckBoxes(); JPanel sizeGroupPanel = createRadioButtons(); // Line up component panels JPanel controlPanel = new JPanel(); controlPanel.setLayout(new GridLayout(3, 1)); controlPanel.add(facenamePanel); controlPanel.add(styleGroupPanel); controlPanel.add(sizeGroupPanel); 객체지향프로그래밍 강원대학교 72 File ChoiceFrame.java 065: 066: 067: 068: 069: 070: 071: 072: 073: 074: 075: 076: 077: 078: 079: 080: 081: 082: // Add panels to content pane add(controlPanel, BorderLayout.SOUTH); } /** Creates the combo box with the font style choices. @return the panel containing the combo box */ public JPanel createComboBox() { facenameCombo = new JComboBox(); facenameCombo.addItem("Serif"); facenameCombo.addItem("SansSerif"); facenameCombo.addItem("Monospaced"); facenameCombo.setEditable(true); facenameCombo.addActionListener(listener); 객체지향프로그래밍 강원대학교 73 File ChoiceFrame.java 083: 084: 085: 086: 087: 088: 089: 090: 091: 092: 093: 094: 095: 096: 097: 098: 099: JPanel panel = new JPanel(); panel.add(facenameCombo); return panel; } /** Creates the check boxes for selecting bold and // italic styles. @return the panel containing the check boxes */ public JPanel createCheckBoxes() { italicCheckBox = new JCheckBox("Italic"); italicCheckBox.addActionListener(listener); boldCheckBox = new JCheckBox("Bold"); boldCheckBox.addActionListener(listener); 객체지향프로그래밍 강원대학교 74 File ChoiceFrame.java 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: JPanel panel = new JPanel(); panel.add(italicCheckBox); panel.add(boldCheckBox); panel.setBorder (new TitledBorder(new EtchedBorder(), "Style")); return panel; } /** Creates the radio buttons to select the font size @return the panel containing the radio buttons */ public JPanel createRadioButtons() { smallButton = new JRadioButton("Small"); smallButton.addActionListener(listener); 객체지향프로그래밍 강원대학교 75 File ChoiceFrame.java 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: mediumButton = new JRadioButton("Medium"); mediumButton.addActionListener(listener); largeButton = new JRadioButton("Large"); largeButton.addActionListener(listener); largeButton.setSelected(true); // Add radio buttons to button group ButtonGroup group = new ButtonGroup(); group.add(smallButton); group.add(mediumButton); group.add(largeButton); 객체지향프로그래밍 강원대학교 76 File ChoiceFrame.java 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: JPanel panel = new JPanel(); panel.add(smallButton); panel.add(mediumButton); panel.add(largeButton); panel.setBorder (new TitledBorder(new EtchedBorder(), "Size")); return panel; } /** Gets user choice for font name, style, and size and sets the font of the text sample. */ public void setSampleFont() { 객체지향프로그래밍 강원대학교 77 File ChoiceFrame.java 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: // Get font name String facename = (String) facenameCombo.getSelectedItem(); // Get font style int style = 0; if (italicCheckBox.isSelected()) style = style + Font.ITALIC; if (boldCheckBox.isSelected()) style = style + Font.BOLD; // Get font size int size = 0; 객체지향프로그래밍 강원대학교 78 File ChoiceFrame.java 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: final int SMALL_SIZE = 24; final int MEDIUM_SIZE = 36; final int LARGE_SIZE = 48; if (smallButton.isSelected()) size = SMALL_SIZE; else if (mediumButton.isSelected()) size = MEDIUM_SIZE; else if (largeButton.isSelected()) size = LARGE_SIZE; // Set font of text field sampleField.setFont(new Font(facename, style, size)); sampleField.repaint(); } 객체지향프로그래밍 강원대학교 79 File ChoiceFrame.java 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: } private private private private private private private private JLabel sampleField; JCheckBox italicCheckBox; JCheckBox boldCheckBox; JRadioButton smallButton; JRadioButton mediumButton; JRadioButton largeButton; JComboBox facenameCombo; ActionListener listener; private static final int FRAME_WIDTH = 300; private static final int FRAME_HEIGHT = 400; 객체지향프로그래밍 강원대학교 80 Advanced Topic: Layout Management 객체지향프로그래밍 강원대학교 81 Advanced Topic: Layout Management 객체지향프로그래밍 강원대학교 82 Advanced Topic: Layout Management 객체지향프로그래밍 강원대학교 83 Menus • • • 프레임은 메뉴바를 가짐 메뉴바는 메뉴를 가짐 메뉴는 서브메뉴와 메뉴아이템을 가짐 객체지향프로그래밍 강원대학교 84 Menus 객체지향프로그래밍 강원대학교 85 Menu Items • 메뉴에 서브메뉴와 메뉴아이템을 넣기 위해서 는 메뉴의 add 메소드를 사용함 JMenuItem fileExitItem = new JMenuItem("Exit"); fileMenu.add(fileExitItem); • • 메뉴아이템은 서브메뉴를 갖지 않음 메뉴아이템은 액션 이벤트를 발생시킴 객체지향프로그래밍 강원대학교 86 Menu Items • 메뉴아이템에는 액션리스너를 등록함 fileExitItem.addActionListener(listener); • 메뉴나 메뉴바에는 액션리스너를 등록하지 않 음 객체지향프로그래밍 강원대학교 87 예 • • • 간단하고 일반적인 메뉴를 구축 각 메뉴아이템으로부터의 이벤트를 처리 각 메뉴 혹은 메뉴 그룹을 만들기 위해 별도의 메소드를 사용 – 읽기 쉽게 – createFaceItem: creates menu item to change the font face – createSizeItem – createStyleItem 객체지향프로그래밍 강원대학교 88 File MenuFrameViewer.java 01: 02: 03: 04: 05: 06: 07: 08: 09: 10: 11: 12: 13: 14: 15: import javax.swing.JFrame; /** This program tests the MenuFrame. */ public class MenuFrameViewer { public static void main(String[] args) { JFrame frame = new MenuFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } } 객체지향프로그래밍 강원대학교 89 File MenuFrame.java 001: 002: 003: 004: 005: 006: 007: 008: 009: 010: 011: 012: 013: 014: 015: 016: import import import import import import import import import import import import import import import import java.awt.BorderLayout; java.awt.Font; java.awt.GridLayout; java.awt.event.ActionEvent; java.awt.event.ActionListener; javax.swing.ButtonGroup; javax.swing.JButton; javax.swing.JCheckBox; javax.swing.JComboBox; javax.swing.JFrame; javax.swing.JLabel; javax.swing.JMenu; javax.swing.JMenuBar; javax.swing.JMenuItem; javax.swing.JPanel; javax.swing.JRadioButton; 객체지향프로그래밍 강원대학교 90 File MenuFrame.java 017: 018: 019: 020: 021: 022: 023: 024: 025: 026: 027: 028: 029: 030: 031: 032: 033: 034: import javax.swing.border.EtchedBorder; import javax.swing.border.TitledBorder; /** This frame has a menu with commands to change the font of a text sample. */ public class MenuFrame extends JFrame { /** Constructs the frame. */ public MenuFrame() { // Construct text sample sampleField = new JLabel("Big Java"); add(sampleField, BorderLayout.CENTER); 객체지향프로그래밍 강원대학교 91 File MenuFrame.java 035: 036: 037: 038: 039: 040: 041: 042: 043: 044: 045: 046: 047: 048: 049: 050: 051: 052: // Construct menu JMenuBar menuBar = new JMenuBar(); setJMenuBar(menuBar); menuBar.add(createFileMenu()); menuBar.add(createFontMenu()); facename = "Serif"; fontsize = 24; fontstyle = Font.PLAIN; setSampleFont(); setSize(FRAME_WIDTH, FRAME_HEIGHT); } /** Creates the File menu. @return the menu */ 객체지향프로그래밍 강원대학교 92 File MenuFrame.java 053: 054: 055: 056: 057: 058: 059: 060: 061: 062: 063: 064: 065: 066: 067: 068: 069: public JMenu createFileMenu() { JMenu menu = new JMenu("File"); menu.add(createFileExitItem()); return menu; } /** Creates the File->Exit menu item and sets its // action listener. @return the menu item */ public JMenuItem createFileExitItem() { JMenuItem item = new JMenuItem("Exit"); class MenuItemListener implements ActionListener { public void actionPerformed(ActionEvent event) 객체지향프로그래밍 강원대학교 93 File MenuFrame.java 070: 071: 072: 073: 074: 075: 076: 077: 078: 079: 080: 081: 082: 083: 084: 085: 086: { System.exit(0); } } ActionListener listener = new MenuItemListener(); item.addActionListener(listener); return item; } /** Creates the Font submenu. @return the menu */ public JMenu createFontMenu() { JMenu menu = new JMenu("Font"); menu.add(createFaceMenu()); 객체지향프로그래밍 강원대학교 94 File MenuFrame.java 087: 088: 089: 090: 091: 092: 093: 094: 095: 096: 097: 098: 099: 100: 101: 102: 103: 104: menu.add(createSizeMenu()); menu.add(createStyleMenu()); return menu; } /** Creates the Face submenu. @return the menu */ public JMenu createFaceMenu() { JMenu menu = new JMenu("Face"); menu.add(createFaceItem("Serif")); menu.add(createFaceItem("SansSerif")); menu.add(createFaceItem("Monospaced")); return menu; } 객체지향프로그래밍 강원대학교 95 File MenuFrame.java 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: /** Creates the Size submenu. @return the menu */ public JMenu createSizeMenu() { JMenu menu = new JMenu("Size"); menu.add(createSizeItem("Smaller", -1)); menu.add(createSizeItem("Larger", 1)); return menu; } /** Creates the Style submenu. @return the menu */ public JMenu createStyleMenu() { 객체지향프로그래밍 강원대학교 96 File MenuFrame.java 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: JMenu menu = new JMenu("Style"); menu.add(createStyleItem("Plain", Font.PLAIN)); menu.add(createStyleItem("Bold", Font.BOLD)); menu.add(createStyleItem("Italic", Font.ITALIC)); menu.add(createStyleItem("Bold Italic", Font.BOLD + Font.ITALIC)); return menu; } /** Creates a menu item to change the font face and // set its action listener. @param name the name of the font face @return the menu item */ public JMenuItem createFaceItem(final String name) { 객체지향프로그래밍 강원대학교 97 File MenuFrame.java 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: JMenuItem item = new JMenuItem(name); class MenuItemListener implements ActionListener { public void actionPerformed(ActionEvent event) { facename = name; setSampleFont(); } } ActionListener listener = new MenuItemListener(); item.addActionListener(listener); return item; } 객체지향프로그래밍 강원대학교 98 File MenuFrame.java 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: /** Creates a menu item to change the font size and set its action listener. @param name the name of the menu item @param ds the amount by which to change the size @return the menu item */ public JMenuItem createSizeItem(String name, final int ds) { JMenuItem item = new JMenuItem(name); class MenuItemListener implements ActionListener { public void actionPerformed(ActionEvent event) { fontsize = fontsize + ds; setSampleFont(); } } 객체지향프로그래밍 강원대학교 99 File MenuFrame.java 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: ActionListener listener = new MenuItemListener(); item.addActionListener(listener); return item; } /** Creates a menu item to change the font style and set its action listener. @param name the name of the menu item @param style the new font style @return the menu item */ public JMenuItem createStyleItem(String name, final int style) { JMenuItem item = new JMenuItem(name); class MenuItemListener implements ActionListener { 객체지향프로그래밍 강원대학교 100 File MenuFrame.java 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203: 204: public void actionPerformed(ActionEvent event) { fontstyle = style; setSampleFont(); } } ActionListener listener = new MenuItemListener(); item.addActionListener(listener); return item; } /** Sets the font of the text sample. */ public void setSampleFont() { 객체지향프로그래밍 강원대학교 101 File MenuFrame.java 205: 206: 207: 208: 209: 210: 211: 212: 213: 214: 215: 216: 217: } 218: 219: Font f = new Font(facename, fontstyle, fontsize); sampleField.setFont(f); sampleField.repaint(); } private private private private JLabel sampleField; String facename; int fontstyle; int fontsize; private static final int FRAME_WIDTH = 300; private static final int FRAME_HEIGHT = 400; 객체지향프로그래밍 강원대학교 102 Text Areas • 문자열을 여러 줄 보이고 싶을 때는 JTextArea 사용 • 행과 열 수를 지정 final int ROWS = 10; final int COLUMNS = 30; JTextArea textArea = new JTextArea(ROWS, COLUMNS); • setText: 화면에 나타날 문자열를 지정 • append: 기존 문자열에 추가 객체지향프로그래밍 강원대학교 103 Text Areas • 줄바꿈을 위해서는 newline 문자 사용 textArea.append(account.getBalance() + "\n"); • 사용자가 편집을 하지 못하게 하려면 textArea.setEditable(false); // program can call setText and append to change it 객체지향프로그래밍 강원대학교 104 Text Areas To add scroll bars to a text area: JTextArea textArea = new JTextArea(ROWS, COLUMNS); JScrollPane scrollPane = new JScrollPane(textArea); 객체지향프로그래밍 강원대학교 105 Text Areas 객체지향프로그래밍 강원대학교 106 File TextAreaViewer.java 01: 02: 03: 04: 05: 06: 07: 08: 09: 10: 11: 12: 13: 14: 15: 16: 17: import import import import import import import import import import java.awt.BorderLayout; java.awt.event.ActionEvent; java.awt.event.ActionListener; javax.swing.JButton; javax.swing.JFrame; javax.swing.JLabel; javax.swing.JPanel; javax.swing.JScrollPane; javax.swing.JTextArea; javax.swing.JTextField; /** This program shows a frame with a text area that displays the growth of an investment. */ public class TextAreaViewer { 객체지향프로그래밍 강원대학교 107 File TextAreaViewer.java 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: public static void main(String[] args) { JFrame frame = new JFrame(); // The application adds interest to this bank account final BankAccount account = new BankAccount(INITIAL_BALANCE); // The text area for displaying the results final int AREA_ROWS = 10; final int AREA_COLUMNS = 30; final JTextArea textArea = new JTextArea( AREA_ROWS, AREA_COLUMNS); textArea.setEditable(false); JScrollPane scrollPane = new JScrollPane(textArea); // The label and text field for entering the // interest rate 객체지향프로그래밍 강원대학교 108 File TextAreaViewer.java 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: JLabel rateLabel = new JLabel("Interest Rate: "); final int FIELD_WIDTH = 10; final JTextField rateField = new JTextField(FIELD_WIDTH); rateField.setText("" + DEFAULT_RATE); // The button to trigger the calculation JButton calculateButton = new JButton("Add Interest"); // The panel that holds the input components JPanel northPanel = new JPanel(); northPanel.add(rateLabel); northPanel.add(rateField); northPanel.add(calculateButton); frame.add(northPanel, BorderLayout.NORTH); frame.add(scrollPane); 객체지향프로그래밍 강원대학교 109 File TextAreaViewer.java 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: class CalculateListener implements ActionListener { public void actionPerformed(ActionEvent event) { double rate = Double.parseDouble( rateField.getText()); double interest = account.getBalance() * rate / 100; account.deposit(interest); textArea.append(account.getBalance() + "\n"); } } ActionListener listener = new CalculateListener(); calculateButton.addActionListener(listener); 객체지향프로그래밍 강원대학교 110 File TextAreaViewer.java 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: } frame.setSize(FRAME_WIDTH, FRAME_HEIGHT); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } private static final double DEFAULT_RATE = 10; private static final double INITIAL_BALANCE = 1000; private static final int FRAME_WIDTH = 400; private static final int FRAME_HEIGHT = 200; 객체지향프로그래밍 강원대학교 111 Swing Documentation을 찾아보는 법 • • 복잡하고 미세한 표현을 위해서는 Swing documentation을 참고해야 함 매우 방대한 문서임 객체지향프로그래밍 강원대학교 112 Example: A Color Mixer • RGB 색깔을 배합하 여 임의의 색깔을 보 임 객체지향프로그래밍 강원대학교 113 Example: A Color Mixer • slider라는 컴포넌트가 있다는 사실을 어떻게 아 는가? – Swing component 책을 사서 본다. – JDK에 들어 있는 sample application을 돌려 본다. – J로 시작하는 모든 클래스를 살펴본다. • JSlider 객체지향프로그래밍 강원대학교 114 Example: A Color Mixer • 다음에 알아야 할 것들 – JSlider는 어떻게 구성하는가? – 사용자가 슬라이더를 움직였을 때 그 사실을 어떻게 알 수 있나? – 사용자가 슬라이더를 어느 값에 세트했는지 어 떻게 알 수 있나? • 기타 – 슬라이더에 눈금은 어떻게 만드나? 등등 객체지향프로그래밍 강원대학교 115 Example: A Color Mixer • JSlider class에는 50개의 고유 메소드와 250개의 상속한 메소드가 있음 • 어떤 메소드는 그 설명이 엄청 어려워 무슨 말 인지 이해할 수 없음 – 기본적인 핵심만 이해하고 이용하면 됨 – 지나치게 복잡하고 지엽적인 내용에 함몰되 지 않는 것이 좋음 객체지향프로그래밍 강원대학교 116 JSlider는 어떻게 구성하나? • • • • API documentation을 찾아봄 여섯개의 구성자 그 중 한두 개 정도 읽어봄 가장 간단한 것과 가장 복잡한 것의 중간 쯤 되 는 것이 통상 효용이 높음 객체지향프로그래밍 강원대학교 117 JSlider는 어떻게 구성하나? • 지나치게 제한적 public JSlider() • Range 0 to 100, initial value of 50 지나치게 복잡 public JSlider(BoundedRangeModel brm) • 실용적 public JSlider(int min, int max, int value) 객체지향프로그래밍 강원대학교 118 사용자가 슬라이더를 움직였을 때 그 사실을 어떻게 알 수 있나? • addActionListener 메소드가 없음 • 아래 메소드가 있음 public void addChangeListener(ChangeListener l) • ChangeListener를 클릭하여 자세히 알아 봄 • 하나의 메소드만을 가짐 void stateChanged(ChangeEvent e) 객체지향프로그래밍 강원대학교 119 사용자가 슬라이더를 움직였을 때 그 사실을 어떻게 알 수 있나? • 사용자가 슬라이더를 움질이면 이 메소드가 호 출될 것임 • ChangeEvent는 무엇인가? – 슈퍼클래스인 EventObject로부터 getSource 메소드를 상속함 – getSource: 어떤 컴포넌트에서 이벤트가 만들어졌는지 알려줌 객체지향프로그래밍 강원대학교 120 사용자가 슬라이더를 움직였을 때 그 사실을 어떻게 알 수 있나? • 아래와 같이 하면 될 것이라는 것을 알게 됨 – 슬라이더에 change event listener를 등록함 – 슬라이더가 변경될 때마다 stateChanged 메소드가 호출됨 – 새로 설정된 슬라이더 값을 읽음 – 색깔 값을 계산함 – 칼라 패널을 repaint 객체지향프로그래밍 강원대학교 121 사용자가 슬라이더를 어느 값에 세트했 는지 어떻게 알 수 있나? • JSlider 클래스에서 get으로 시작하는 메소드를 살펴보면 아래 메소드를 찾을 수 있음 public int getValue() 객체지향프로그래밍 강원대학교 122 The Components of the SliderFrame 객체지향프로그래밍 강원대학교 123 File SliderFrameViewer.java 01: 02: 03: 04: 05: 06: 07: 08: 09: 10: 11: 12: import javax.swing.JFrame; public class SliderFrameViewer { public static void main(String[] args) { SliderFrame frame = new SliderFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } } 객체지향프로그래밍 강원대학교 124 File SliderFrame.java 01: 02: 03: 04: 05: 06: 07: 08: 09: 10: 11: 12: 13: 14: 15: 16: import import import import import import import import import java.awt.BorderLayout; java.awt.Color; java.awt.GridLayout; javax.swing.JFrame; javax.swing.JLabel; javax.swing.JPanel; javax.swing.JSlider; javax.swing.event.ChangeListener; javax.swing.event.ChangeEvent; public class SliderFrame extends JFrame { public SliderFrame() { colorPanel = new JPanel(); 객체지향프로그래밍 강원대학교 125 File SliderFrame.java 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: add(colorPanel, BorderLayout.CENTER); createControlPanel(); setSampleColor(); setSize(FRAME_WIDTH, FRAME_HEIGHT); } public void createControlPanel() { class ColorListener implements ChangeListener { public void stateChanged(ChangeEvent event) { setSampleColor(); } } 객체지향프로그래밍 강원대학교 126 File SliderFrame.java 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: ChangeListener listener = new ColorListener(); redSlider = new JSlider(0, 100, 100); redSlider.addChangeListener(listener); greenSlider = new JSlider(0, 100, 70); greenSlider.addChangeListener(listener); blueSlider = new JSlider(0, 100, 70); blueSlider.addChangeListener(listener); JPanel controlPanel = new JPanel(); controlPanel.setLayout(new GridLayout(3, 2)); controlPanel.add(new JLabel("Red")); controlPanel.add(redSlider); 객체지향프로그래밍 강원대학교 127 File SliderFrame.java 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: controlPanel.add(new JLabel("Green")); controlPanel.add(greenSlider); controlPanel.add(new JLabel("Blue")); controlPanel.add(blueSlider); add(controlPanel, BorderLayout.SOUTH); } /** Reads the slider values and sets the panel to the selected color. */ public void setSampleColor() { // Read slider values 객체지향프로그래밍 강원대학교 128 File SliderFrame.java 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: } float red = 0.01F * redSlider.getValue(); float green = 0.01F * greenSlider.getValue(); float blue = 0.01F * blueSlider.getValue(); // Set panel background to selected color colorPanel.setBackground(new Color(red, green, blue)); colorPanel.repaint(); } private private private private JPanel colorPanel; JSlider redSlider; JSlider greenSlider; JSlider blueSlider; private static final int FRAME_WIDTH = 300; private static final int FRAME_HEIGHT = 400; 객체지향프로그래밍 강원대학교 129