GUI 이벤트, 이벤트 리스너와 이벤트 소스 그림 그리기 내부 클래스
창 Jframe의 모양(Metal L&F) Jframe의 모양(Aqua L&F)
창을 만드는 방법 프레임(JFrame) 만들기 위젯 만들기 위젯을 프레임에 추가 화면에 표시 JFrame frame = new JFrame(); 위젯 만들기 JButton button = new JButton(“click me”); 위젯을 프레임에 추가 frame.getContentPane().add(button); 화면에 표시 frame.setSize(300, 300); frame.setVisible(true);
버튼 import javax.swing.*; public class SimpleGui1 { public static void main(String[] args) { JFrame frame = new JFrame(); JButton button = new JButton(“click me”); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().add(button); frame.setSize(300, 300); frame.setVisible(true); }
이벤트 사용자가 클릭했을 때 호출할 메소드 그 메소드를 언제 실행시켜야 할지 알아내는 방법 코드 Button 객체 public void changeIt() { button.setText(“I’ve been clicked!”); } 코드 Button 객체
리스너 인터페이스 이벤트 소스(event source) 리스너(listener) 인터페이스 사용자의 행동을 이벤트로 바꿔주는 객체 java.awt.event 패키지 리스너(listener) 인터페이스 리스너와 이벤트 소스를 연결해주는 다리 역할을 함 필요한 이벤트 유형에 맞는 리스너 인터페이스를 구현하면 그 이벤트를 받아올 수 있습니다. ActionListener actionPerformed(ActionEvent ev) KeyListener KeyPressed(KeyEvent ev) KeyReleased(KeyEvent ev) KeyTyped(KeyEvent ev) ItemListener itemStateChanged(ItemEvent ev)
리스너와 소스 button.addActionListener(this) actionPerformed(theEvent)
ActionEvent를 받는 방법 ActionListener 인터페이스 구현 버튼에 등록 이벤트 처리 메소드 구현 import javax.swing.*; import java.awt.event.*; public class SimpleGui1B implements ActionListener { JButton button; public static void main(String[] args) { SimpleGui1B = new SimpleGui1B(); gui.go(); } public void go() { JFrame frame = new JFrame(); button = new JButton(“click me”); button.addActionListener(this); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().add(button); frame.setSize(300, 300); frame.setVisible(true); public void actionPerformed(ActionEvent ev) { button.setText(“I’ve been clicked!”);
이벤트 소스인지 알아내는 방법 API 문서를 찾아보면 됩니다. add로 시작하고 Listener로 끝나는 이름을 가지고 리스너 인터페이스 인자를 받아들이는 메소드가 있는지 찾아보면 됩니다. addKeyListener(KeyListener k) addActionListener(ActionListener a)
GUI에 요소를 추가하는 방법 프레임에 위젯을 집어넣는 방법 위젯에 2D 그래픽을 그리는 방법 frame.getContentPane().add(myButton); 위젯에 2D 그래픽을 그리는 방법 graphics.fillOval(70, 70, 100, 100); 위젯에 그림 파일을 집어넣는 방법 graphics.drawImage(myPic, 10, 10, this);
그림을 그리기 위한 위젯 JPanel의 하위클래스를 만들고 paintComponent()라는 메소드를 오버라이드 시스템에서 위젯을 화면에 표시하기 위해 호출하는 메소드 그래픽 관련 코드는 대부분 여기에 집어넣습니다. JVM에서 화면을 갱신할 때마다 호출됩니다. 사용자가 직접 호출하는 일은 절대 없습니다. 대신 repaint() 메소드를 호출하면 화면이 갱신되면서 이 메소드가 실행됩니다.
paintComponent() import java.awt.*; import javax.swing.*; class MyDrawPanel extends JPanel { public void paintComponent(Graphics g) { g.setColor(Color.orange); g.fillRect(20, 50, 100, 100); }
paintComponent() JPEG 파일 표시 그리기 public void paintComponent(Graphics g) { Image image = new ImageIcon(“catzilla.jpg”).getImage(); g.drawImage(image, 3, 4, this); } 그리기 g.fillRect(0, 0, this.getWidth(), this.getHeight()); int red = (int) (Math.random() * 255); int green = (int) (Math.random() * 255); int blue = (int) (Math.random() * 255); Color randomColor = new Color(red, green, blue); g.setColor(randomColor); g.fillOval(70, 70, 100, 100);
Graphics2D g 매개변수는 사실 Graphics2D 객체를 참조함 public void paintComponent(Graphics g) { g 매개변수는 사실 Graphics2D 객체를 참조함 Animal a = new Dog(); a.bark(); Dog d = (Dog) a; d.bark(); Graphics2D g2d = (Graphics2D) g;
이벤트를 받아서 그림을 고쳐그리는 방법
GUI 레이아웃 코드를 직접 입력해서 실행해봅시다. 한 프레임에 두 개 이상의 위젯을 넣는 방법 frame.getContentPane().add(button); frame.getContentPane().add(BorderLayout.CENTER, button); 북쪽(NORTH) 서쪽 (WEST) 중앙 (CENTER) 동쪽 (EAST) 남쪽(SOUTH) 코드를 직접 입력해서 실행해봅시다.
버튼이 두 개 있으면? 북쪽(NORTH) 서쪽 (WEST) 중앙 (CENTER) 동쪽 (EAST) 남쪽(SOUTH)
여러 개의 이벤트를 처리하는 방법 actionPerformed() 메소드를 두 개 구현 class MyGui implements ActionListener { …… public void actionPerformed(ActionEvent ev) { frame.repaint(); } label.setLabel(“That hurt!”);
여러 개의 이벤트를 처리하는 방법 똑같은 리스너를 두 버튼에 모두 등록 class MyGui implements ActionListener { …… public void go() { colorButton = new JButton(); labelButton = new JButton(); colorButton.addActionListener(this); labelButton.addActionListener(this); } public void actionPerformed(ActionEvnet ev) { if (event.getSource() == colorButton) { frame.repaint(); } else { label.setLabel(“That hurt!”);
여러 개의 이벤트를 처리하는 방법 각 버튼마다 별도의 ActionListener 클래스 제작 class MyGui { JFrame frame; JLabel label; void gui() { … } class ColorButtonListener implements ActionListener { public void actionPerformed(ActionEvent ev) { frame.repaint(); class LabelButtonListener implements ActionListener { label.setLabel(“That hurt!”);
내부 클래스 내부 클래스(inner class) 외부 클래스에 있는 것을 마음대로 사용할 수 있음 class MyOuterClass { private int x; class MyInnerClass { void go() { x = 42; }
2. 외부클래스의 인스턴스를 이용하여 내부클래스의 인스턴스를 만듭니다. 내부 클래스와 외부 클래스 인스턴스 1. 외부클래스 인스턴스를 만듭니다. 2. 외부클래스의 인스턴스를 이용하여 내부클래스의 인스턴스를 만듭니다. MyOuter 객체 MyInner 객체 int x 3. 외부 객체와 내부 객체는 각별한 사이가 됩니다. String s 외부 객체 내부 객체
내부 클래스의 인스턴스 일반 클래스의 인스턴스를 만들 때와 똑같은 식으로 하면 됩니다. class MyOuter { private int x; MyInner inner = new MyInner(); public void doStuff() { inner.go(); } class MyInner { void go() { x = 42;
애니메이션 특정 좌표에 객체를 그림 다른 좌표에 객체를 서로 그림 좌표를 바꿔가면서 위의 단계 반복 g.fillOval(20, 50, 100, 100); 다른 좌표에 객체를 서로 그림 g.fillOval(25, 55, 100, 100); 좌표를 바꿔가면서 위의 단계 반복
애니메이션 x, y 좌표는 어디에서 바꿀까? repaint()는 어디에서 호출할까? 예제를 직접 입력하여 실행해봅시다. class MyDrawPanel extends JPanel { public void paintComponent(Graphics g) { g.setColor(Color.orange); g.fillOval(x, y, 100, 100); } x, y 좌표는 어디에서 바꿀까? repaint()는 어디에서 호출할까? 그림 패널을 내부 클래스로… paintComponent에서 순환문을 쓰지 않고… 예제를 직접 입력하여 실행해봅시다.
뮤직 비디오(?)
GUI와 무관한 이벤트 미디 이벤트를 받아서 처리해야 함 ControllerEvent라는 이벤트를 사용 미디 이벤트(NOTE ON 이벤트)를 직접 받아 쓸 수 없음 ControllerEvent라는 이벤트를 사용 첫 번째 박자 – NOTE ON, ControllerEvent 두 번째 박자 – NOTE OFF 세 번째 박자 – NOTE ON, ControllerEvent 네 번째 박자 – NOTE OFF
메시지를 쉽게 만드는 방법 메시지 인스턴스 만들기 SetMessage()를 호출하여 지시사항 전달 ShortMessage first = new ShortMessage(); SetMessage()를 호출하여 지시사항 전달 first.setMessage(192, 1, instrument, 0); 메시지에 대한 MidiEvent 인스턴스 만들기 MidiEvent noteOn = new MidiEvent(first, 1); 이벤트를 트랙에 추가 track.add(noteOn); ShortMessage a = new ShortMessage(); a.setMessage(144, 1, 44, 100); MidiEvent noteOn = new MidiEvent(a, 1); track.add(noteOn);
메시지/이벤트를 만들기 위한 메소드 각 예제를 직접 입력하여 실행해봅시다. public static MidiEvent makeEvent(int comd, int chan, int one, int two, int tick) { MidiEvent event = null; try { ShortMessage a = new ShortMessage(); a.setMessage(comd, chan, one, two); event = new MidiEvent(a, tick); } catch(Exception ex) { } return event; } 각 예제를 직접 입력하여 실행해봅시다.
숙제 본문을 꼼꼼하게 읽어봅시다. 코드를 전부 입력해서 실행시켜보고 조금씩 고쳐봅시다. 장 중간 및 맨 끝에 나와있는 모든 연습문제를 자기 힘으로 해결해봅시다. API 문서에서 이 장에 나와있는 클래스 및 메소드에 대한 내용을 직접 찾아봅시다.