[JAVA] chapter 10. 자바의 이벤트 처리

walnut_mr·2024년 12월 27일

JAVA

목록 보기
10/11
  • 10장 - 자바의 이벤트 처리

    • event 기반 프로그래밍 - event listener

      ↔ batch programming (개발자가 흐름 결정 방식)

      처리 순서 : event 발생 > event 객체 생성 > event listener 찾기 > 호출 > 실행

      event source - GUI component // ex) JButton component
      event 객체 - event 정보(종류, 소스, 화면 좌표, 마우스 버튼 종류, 눌린 키)
      event listener - event 처리 코드 (component에 등록 되어야 작동 가능)
      event 분배 thread - 무한 루프 실행 thread
      // JVM으로부터 이벤트 발생 통지 받음 > 이벤트 소스, 종류 결정 > 객체 생성 > 리스너 호출
    • event 객체

      현재 발생한 event 관련 정보 담은 객체 (event listener에 전달됨)

      java.util.EventObject 에 상속 받음 (최상위 클래스)

      import java.awt.event.*;
      import javax.swing.event.*;
      
      // event 객체 정보
      ActionEvent - action 문자열
      MouseEvent - mouse 위치 정보, 버튼, 함께 눌린 키 정보 등
      ItemEvent - item check 상태
      // getSource - 이벤트 소스 받기 (Object 타입)
      JButton b = (JButton)event.getSource();
      
      // ex
      event 객체 - MouseEvent
      event source - Component // 무슨 컴포넌트를 누른거냐
      event 발생 경우 - 7
    • event listener - interface의 모든 추상 method 다 구현 필요 !!

      JDK에서 interface 제공 (상속, 추상 메소드 모두 구현 필요)

      // mouse click 시 event listener 순서
      mousePressed > mouseReleased > mouseClicked
      // ActionListener
      // 추상 method 모두 구현 필요
      interface ActionListener {
      		public void actionPerformed(ActionEvent e);
      }
      
      // MouseListener
      interface MouseListener {
      		public void mousePressed(MouseEvent e);
      		public void mouseReleased(MouseEvent e);
      		public void mouseClicked(MouseEvent e);
      		public void mouseEntered(MouseEvent e);
      		public void mouseExited(MouseEvent e);
      }

      event listener 작성 과정

      1. 이벤트, 이벤트 리스너 선택 (이벤트 타입, 이벤트 리스너, 이벤트 객체)

      2. listener class 작성 (추상 메소드 모두 구현)

      3. listener 등록 (swing component에 event listener 등록)

        // 1. 선택 (이벤트 : Action 이벤트, 리스너 : ActionListener, 객체, ActionEvent)
        // 2. listener class 작성
        class MyActionListener implements ActionListener {
        		public void actionPerformed(ActionEvent e) { // ActionListener의 method 구현
        				JButoon b = (JButton)e.getSource(); // 이벤트 소스
        				if (b.getText().equals("Action"))
        						b.setText("액션");
        				else
        						b.setText("Action");
        		}
        }
        // 3. listener 등록
        MyActionListener listener = new MyActionListener(); // 객체 생성
        btn.addActionListener(listener); // button component에 등록
        
        // 등록 시 유의사항 - 모든 component가 해당 listener를 갖고 있는건 아님
        JButton b = new JButton("test");
        b.addItemListener(listener); // error - JButton에는 addItemListener 없음
        
        JScrollBar s = new JScrollBar();
        s.addActionListener(listener); // error - JScrollBar에 addActionListener 없음
    • event listener 작성 방법 - (독립 class, 내부 class, 익명 class)

      // 독립 class로 작성 - 리스너를 완전한 class로
      // 리스너를 "여러 곳"에서 사용할 때 적합
      // 다른 class이므로 IndepClassListener의 멤버 접근 불가
      import java.awt.*;
      import java.awt.event.*;
      import javax.swing.*;
      
      public class IndepClassListener extends JFrame {
      		public IndepClassListener() {
      				setTitle("Action 이벤트 리스너 예제");
      				setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      				
      				Container c = getContentPane();
      				c.setLayout(new FlowLayout());
      				
      				JButton btn = new JButton("Action");
      				btn.addActionListener(new MyActionListener()); // 리스너 등록
      				c.add(btn);
      				
      				setSize(350, 150);
      				setVisible(true);
      		}
      		public static void main(String[] args) {
      				new IndepClassListener();
      		}
      }
      
      // 독립 class로
      class MyActionListener implements ActionListener { // interface ActionListener 상속
      		public void actionPerformed(ActionEvent e) {
      				JButton b = (JButton)e.getSource(); // 이벤트 소스 받기 (JButton)
      				if (b.getText().equals("Action"))
      						b.setText("액션");
      				else
      						b.setText("Action");
      		}
      }
      // 내부 class로 - class안에 멤버처럼
      // 리스너를 "특정 class에서만" 사용할 때 적합
      // 상속 부모 class, JFrame 멤버 접근 가능
      import java.awt.*;
      import java.awt.event.*;
      import javax.swing.*;
      
      public class InnerClassListener extend JFrame {
      		public InnerClassListener() {
      				setTitle("Action 이벤트 리스너 예제");
      				setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      				
      				Container c = getContentPane();
      				c.setLayout(new FlowLayout());
      				
      				JButton btn = new JButton("Action");
      				btn.addActionListener(new MyActionListener()); // 리스너 등록
      				c.add(btn);
      				
      				setSize(350, 150);
      				setVisible(true);
      		}
      		
      		// 내부 class로
      		private class MyActionListener implements ActionListener {
      				public void actionPerformed(ActionEvent e) {
      						JButton b = (JButton)e.getSource(); // 이벤트 소스 받기 (JButton)
      						if (b.getText().equals("Action"))
      								b.setText("액션");
      						else
      								b.setText("Action");
      								
      						InnerClassListener.this.setTitle(b.getText());
      				}
      		}
      		
      		public static void main(String[] args) {
      				new InnerClassListener();
      		}
      }
      // 익명 class - class 이름 없이 간단히 리스너 작성
      // class 필요없이 호출 부분에 연달아 작성 - 바로 객체 생성
      // class 정의 + instance 생성 한 번에
      import java.awt.*;
      import java.awt.event.*;
      import javax.swing.*;
      
      public class AnonymousClassListener extend JFrame {
      		public AnonymousClassListener() {
      				setTitle("Action 이벤트 리스너 예제");
      				setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      				
      				Container c = getContentPane();
      				c.setLayout(new FlowLayout());
      				
      				JButton btn = new JButton("Action");
      				// 익명 class로
      				btn.addActionListener(new MyActionListener() {
      						public void actionPerformed(ActionEvent e) {
      								JButton b = (JButton)e.getSource();
      								if (b.getText().equals("Action")
      										b.setText("액션");
      								else
      										b.setText("Action");
      										
      								setTitle(b.getText);
      						}
      				}); // 리스너 등록
      				c.add(btn);
      				
      				setSize(350, 150);
      				setVisible(true);
      		}
      		
      		public static void main(String[] args) {
      				new InnerClassListener();
      		}
      }
      // 예제 10-4
      import java.awt.*;
      import java.awt.event.*;
      import javax.swing.*;
      
      public class MouseListenerEx extends JFrame {
      		private JLabel la = new JLabel("Hello");
      		
      		public MouseListenerEx() {
      				setTitle("Mouse이벤트 예제");
      				setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      				
      				Container c = getContentPane();
      				c.addMouseListener(new MyMouseListener());
      		
      				c.setLayout(null);
      				la.setSize(50, 20);
      				la.setLocation(30, 30);
      				c.add(la);
      				
      				setSize(250, 250);
      				setVisible(true);
      		}
      		
      		class MyMouseListener implements MouseListener {
      				public void mousePressed(MouseEvent e) {
      						int x = e.getX();
      						int y = e.getY();
      						la.setLocation(x - 13, y - 10);
      				}
      				public void mouseReleased(MouseEvent e) { }
      				public void mouseClicked(MouseEvent e) { }
      				public void mouseEntered(MouseEvent e) { }
      				public void mouseExited(MouseEvent e) { }
      		}
      		
      		public static void main(String[] args) {
      				new MouseListenerEx();
      		}
      }
    • Adapter class - event listener의 모든 추상 method 구현해야하는 불편 해결

      listener의 모든 method가 단순 return 하도록 구현한 class

      추상 method가 하나인 listener는 adapter class 없음 (ActionListener, ItemListener)

      // Adapter class
      class MouseAdapter implements MouseListener, MouseMotionListener, MouseWheelListener {
      		public void mousePressed(MouseEvent e) { }
      		public void mouseReleased(MouseEvent e) { }
      		public void mouseClicked(MouseEvent e) { }
      		public void mouseEntered(MouseEvent e) { }
      		public void mouseExited(MouseEvent e) { }
      		public void mouseDragged(MouseEvent e) { }
      		public void mouseMoved(MouseEvent e) { }
      		public void mouseWheelMoved(MouseEvent e) { }
      }
      // MouseAdapter로 예제 10-4 수정
      import java.awt.*;
      import java.awt.event.*;
      import javax.swing.*;
      
      class MouseAdapterEx extends JFrmae {
      		private JLabel la = new JLabel("Hello");
      		public MouseAdapterEx() {
      				setTitle("Mouse이벤트 예제");
      				setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      				
      				Container c = getContentPane();
      				c.addMouseListener(new MyMouseAdapter());
      		
      				c.setLayout(null);
      				la.setSize(50, 20);
      				la.setLocation(30, 30);
      				c.add(la);
      				
      				setSize(250, 250);
      				setVisible(true);
      		}
      		
      		class MyMouseAdapter extends MouseAdapter { // class라 extends
      				public void mousePressed(MouseEvent e) { // 필요한 method만 구현
      						int x = e.getX();
      						int y = e.getY();
      						la.setLocation(x, y);
      				}
      		}
      		public static void main(String[] args) {
      				new MouseAdapterEx();
      		}
    • Key 이벤트, KeyListener

      key event - 사용자 키 입력 시 발생하는 event (모든 component가 수신 가능)

      foucs - key 입력 독점권 (focus를 가진 component에만 key event 전달됨)

      // focus 설정 방법 - 아래 2개 line 필요
      component.setFocusable(true); // focus 가능하도록 지정
      component.requestFocus(); // foucs 강제 지정
      
      // focus 주는 타이밍 1 - setVisible 직후 (focus 임의 움직임 이슈)
      setVisible(true);
      component.setFocusable(true);
      component.requestFocus();
      
      // focus 주는 타이밍 2 - mouse로 component 클릭할 때
      component.addMouseListener(new MouseAdapter() {
      		public void mouseClicked(MouseEvent e) {
      				Component c = (Component)e.getSource(); // mouse로 클릭한 컴포넌트
      				c.setFocusable(true);
      				c.requestFocus(); // 마우스로 클릭한 컴포넌트에게 focus
      		}
      });
      // KeyListener method
      void keyPressed(KeyEvent e) { ... } // key 눌린 순간
      void keyReleased(KeyEvent e) { ... } // key 뗀 순간
      void keyTyped(KeyEvent e) { ... } // key 뗀 순간 (Unicode에서 추가 발생)
      // Unicode = 알파벳, 숫자, 문자 기호 등 (F1, home, del 등은 unicode X)
      
      // 실행 순서 (ex. 'f' 누름)
      keyPressed() -> keyTyped() -> keyReleased()// 'home'키 누름
      keyPressed() -> keyReleased()

      가상 키 (virtual key) - 어떤 key인지 비교 판단 가능

      KeyEvent class에 VK_로 시작하는 static 상수로 선언

      // 입력된 key 판별 방법
      // key의 unicode return (문자 키에만 작동) - unicode X = CHAR_UNDEFINED return
      public void keyPressed(KeyEvent e) {
      		if (e.getKeyChar() == 'q') // 'q' 누르면 종료
      				System.exit(0);
      }
      
      // key code 값 return
      public void keyPressed(KeyEvent e) {
      		if (e.getKeyCode() == KeyEvent.VK_F5) // 'F5' 누르면 종료 (가상 키 값 비교)
      				System.exit(0);
      }
      
      // key 이름 문자열 return ("SHIFT", "F1") - static method
      static String KeyEvent.getKeyText(int keyCode);
    • MouseEvent, MouseListener, MouseMotionListener, MouseWheelListener

      // mouse 눌린 위치에서 떼어지는 경우 호출 순서
      mousePressed() -> mouseReleased() -> mouseClicked()
      // Released() : 마우스 떼면 무조건 호출
      // Clicked() : 누른 위치 = 뗀 위치 (이동 X) 에만 호출
      
      // mouse 드래그 시 호출 순서
      mousePressed() -> mouseDragged() -> mouseDragged -> ... -> mouseReleased()
      // MouseListener - method 5개
      void mousePressed(MouseEvent e) {}
      void mouseReleased(MouseEvent e) {}
      void mouseClicked(MouseEvent e) {}
      void mouseEntered(MouseEvent e) {}
      void mouseExited(MouseEvent e) {}
      
      // MouseMotionListener - method 2개
      void mouseDragged(MouseEvent e) {}
      void mouseMoved(MouseEvent e) {}
      
      // MouseWheelListener - method 1개
      void mouseWheelMoved(MouseWheelEvent e) {}
      // MouseEvent 객체 - MouseEvent, MouseMotionEvent의 정보
      public void mousePressed(MouseEvent e) {
      		int x = e.getX();
      		int y = e.getY();
      }
      public void mouseClicked(MouseEvent e) {
      		if (e.getClickCount() == 2) { ... }
      }
      public void mousePressed(MouseEvent e) {
      		if (e.getButton() == MouseEvent.BUTTON1)
      				System.out.println("Left Button Pressed");
      }
      
      // MouseWheelEvent 객체 - MouseWheelEvent의 정보
      public void mouseWheelMoved(MouseWheelEvent e) {
      		... // wheel 움직임 따라 event 처리
      }
profile
https://github.com/khkim09

0개의 댓글