c23 [Java] 이벤트 처리
본문 바로가기
[Java]

[Java] 이벤트 처리

by Jarvis2304 2023. 11. 11.

▶이벤트 기반 프로그래밍

● 이벤트의 발생에 의해 프로그램 흐름이 결정되는 방식

- 이벤트가 발생하면 이벤트를 처리하는 루틴(이벤트 리스너) 실행

- 프로그램 내에 어떤 코드가 언제 실행될지 이벤트 발생의 의해 전적으로 결정

 

 

● 이벤트 종류

- 사용자의 입력(마우스 드래그, 마우스 클릭, 키보드 입력 등)

- 센서로부터의 입력, 네트워크로부터 데이터 통신

- 다른 응용 프로그램이나 다른 스레드로부터의 메시지

 

 

● 반대되는 개념: 배치 실행(batch programming)

- 프로그램의 개발자가 프로그램의 흐름을 결정하는 방식

 

▷이벤트 기반 프로그램의 구조

- 이벤트 리스너들의 집합

 

▷이벤트 처리 순서

1) 이벤트 발생 :마우스 드래그, 마우스 클릭, 키보드 입력 등

2) 이벤트 객체 생성 :현재 발생한 이벤트에 대한 정보를 가진 객체

3) 이벤트 리스너 찾기 

4) 이벤트 리스너 호출 :이벤트 객체가 리스너에 전달됨

5) 이벤트 리스너 실행

 

 

예제)  이벤트 발생 사례

 

 

 

 

 

예제) 자바 스윙 GUI 응용프로그램의 이벤트 처리 과정

1) 사용자가 마우스로 화면의 New 버튼을 클릭

2) 버튼 클릭은 운영체제의 마우스 드라이버를 거쳐 자바 가상 기계에 전달

3) 자바 가상 기계는 이벤트 분배 스레드(Event Dispatch Thread)에게 마우스 클릭에 관한 정보를 보냄

4) 이벤트 분배 스레드는 이벤트 객체를 생성, 이벤트 객체는 이벤트에 관한 여러 정보를 담은 객체.

    이벤트 객체 내에 저장되는 정보 중, 특별히 이벤트를 발생시킨 컴포넌트를 이벤트 소스라고 부름.

    여기서 이벤트 소스는 'New' 글자가 새겨진 JButton 컴포넌트

 

5) 이벤트 분배 스레드는 JButton에 연결된 '이벤트 리스너 4'를 찾아 호출

6) 이벤트 분배 스레드는 '이벤트 리스너4'로부터 리턴한 후 다음 이벤트를 기다림

(자바에서 이벤트는 이벤트 분배 스레드에 의해 하나씩 도착하는 순서대로 처리, 하나의 이벤트에 대한 처리가 완전히 종료된 후 다음 이벤트가 처리됨. 사용자가 "New" 버튼을 클릭하고 그에 대한 처리가 끝나면, 다음 이벤트를 기다리는 단계를 의미)

 

● 이벤트 소스

- 이벤트를 발생시킨 GUI 컴포넌트

 

● 이벤트 객체

- 발생한 이벤트에 대한 정보  ex)이벤트 종류, 이벤트 소스, 화면 좌표, 마우스 버튼 종류, 눌러진 키

 

● 이벤트 리스너

- 이벤트를 처리하는 코드

- 컴포넌트에 등록되어야 작동 가능

 

● 이벤트 분배 스레드

○ 동작과정

- 자바 가상 기계로부터 이벤트 발생의 통지 받음

- 이벤트 소스와 이벤트 종류 결정

- 적절한 이벤트 객체 생성, 이벤트 리스너 찾아 호출

- 무한 루프를 실행하는 스레드

 

 

 

 

 

 

 

▶이벤트 객체

- 이벤트가 발생할 때, 발생한 이벤트에 관한 정보를 가진 객체

- 이벤트 리스너에 전달됨 (이벤트 리스너 코드에서 이벤트가 발생한 상황을 파악할 수 있게 함)

 

● 이벤트 객체의 종류

 

 

이벤트 객체가 포함하는 정보

- 이벤트 종류

- 이벤트 소스

- 이벤트가 발생한 화면 좌표

- 이벤트가 발생한 컴포넌트 좌표

- 버튼이나 메뉴 아이템에 이벤트가 발생한 경우, 버튼이나 메뉴 아이템의 문자열

- 클릭된 마우스 버튼 번호

- 키가 눌러졌다면 키의 코드 값과 문자 값

- 체크박스, 라디오버튼 등과 같은 컴포넌트에 이벤트가 발생하였다면 체크 상태

 

  이벤트에 따라 조금씩 다른 정보 포함

- ActionEvent 객체: 액션 문자열

- MouseEvent 객체: 마우스의 위치 정보, 마우스 버튼, 함께 눌러진 키 정보 등

- ItemEvent 객체: 아이템의 체크 상태

 

 

 

▷이벤트 객체의 메소드

- 이벤트 객체는 메소드를 통해 이벤트 정보를 제공

 

  이벤트 소스 알아내기

○ Object EventObject.getSource()

- 발생한 이벤트의 소스 컴포넌트 리턴

- Object 타입으로 리턴하므로 캐스팅하여 사용

- 모든 이벤트 객체에 대해 적용

 

 

 

▷이벤트 객체와 이벤트 소스

 

 

 

 

▶이벤트 리스너

- 이벤트를 처리하는 코드, 클래스로 작성

 

JDK에서 이벤트 리스너 작성을 위한 인터페이스 제공

- 개발자가 리스너 인터페이스의 추상 메소드 구현

- 이벤트가 발생하면 자바 플랫폼은 리스너 인터페이스의 추상 메소드 호출

 

ex) ActionListener 인터페이스

 

 

ex) MouseListener

 

 

 

▷리스너 인터페이스와 메소드

표1

 

 

 

▷이벤트 리스너 작성 과정

● 3단계 과정으로 작성

1) 이벤트와 이벤트 리스너 선택 :목적에 적합한 이벤트 리스너 인터페이스 선택

2) 이벤트 리스너 클래스 작성 :리스너 인터페이스를 상속받는 클래스 작성, 추상 메소드 모두 구현

3) 이벤트 리스너 등록 :이벤트를 받을 스윙 컴포넌트에 이벤트 리스너 등록

 

예제 ) 버튼을 클릭하면 버튼 문자열을 "Action"과 "액션"으로 번걸아 바꾸는 이벤트 리스너

 

1) 이벤트와 이벤트 리스너 선택

- 표1을 보면, 버튼을 클릭(선택)할 때 발생하는 이벤트와 이벤트 리스너 인터페이스, 이벤트 객체는 다음과 같음

  • 이벤트: Action 이벤트
  • 이벤트 리스너: ActionListener
  • 이벤트 객체: ActionEvent

 

 

2) 이벤트 리스너 클래스 작성 

- ActionListener 인터페이스를 상속받은 MyActionListener 클래스를 선언하고, 한 개뿐인 추상 메소드 actionPerformed(ActionEvent e)를 다음과 같이 작성

class MyActionListener implements ActionListener{

	public void actionPerformed(ActionEvent e){ //버튼 클릭 시 호출되는 메소드
    
	JButton b = (JButton)e.getSource(); //클릭된 버튼 알아내기

	if(b.getText().equals("Action"))
	b.setText("액션");
	else
	b.setText("Action");
	}
}

 

 

3) 이벤트 리스너 등록

- 이벤트 리스너가 작동하기 위해서는 MyActionListener의 객체를 생성하여 이벤트를 처리할 버튼 컴포넌트에 등록해야 함

MyActionListener listener = new MyActionListener(); //리스너 객체 생성
btn.addActionListener(listner); //리스너 등록

 

 

- 일반적으로 컴포넌트  component에 이벤트 리스너를 등록하기 위해서는 다음형식과 같은  메소드 사용

- XXX는 이벤트 이름에 해당함

component.addXXXListener(listener)

 

 

 

 

▷리스너 등록 메소드가 addXXXListener인 이유는?

● 컴포넌트는 다른 이벤트에 대한 리스너를 동시에 가질수 있다

JButton.addActionListener(); // Action 리스너

JButton.addKeyListener(); // Key 리스너

JButton.addFocusListener(); // Focus 리스너

 

 

● 컴포넌트는 한 이벤트에 대해 여러 개의 리스너를 동시에 가질 수 있다

JButton.addActionListener(new MyButtonListener1());

JButton.addActionListener(new MyButtonListener2());

JButton.addActionListener(new MyButtonListener3());

- 이때 리스너는 등록된 반대 순으로 모두 실행됨

 

 

 

 

 

 

 

▷이벤트 리스너 작성 방법

● 3가지 방법

1) 독립 클래스로 작성

- 이벤트 리스너를 완전한 클래스로 작성

- 이벤트 리스너를 여러 곳에서 사용할 때 적합

 

2) 내부 클래스로 작성

- 클래스 안에 멤버처럼 클래스 작성

- 이벤트 리스너를 특정 클래스에서만 사용할 때 적합

 

3) 익명 클래스로 작성

- 클래스의 이름 없이 간단한 리스너 작성

- 클래스 조차 만들 필요 없이 리스너 코드가 간단한 경우에 적합

 

예제 1) 독립 클래스로 Action 이벤트의 리스너 작성

 

 

예제 2) 내부 클래스로 Action 이벤트 리스너 만들기

 

 

 

 

 

● 익명 클래스

- (클래스 정의 + 인스턴스 생성)을 한번에 작성

 

ex) ActionListener를 구현하는 익명의 이벤트 리스너 작성 예시

- (a)는 MyActionListener클래스를 작성한 사례로, ActionListener를 상속받아 클래스를 작성하고 new로 객체를 생성하는 부분이 나눠어져 있음

 

- (b)는 ActionListener 인터페이스를 상속받으면서 바로 actionPerformed()메소드를 구현한 코드 블록, 즉 익명 클래스를 작성하고 new로 생성

 

 

 

 

예제 3) 익명 클래스로 Action 이벤트 리스너 만들기

 

 

 

 

 

예제 4) 마우스로 문자열 이동시키기(마우스 이벤트 연습) 

 

 

 

 

 

 

 

▶어댑터(Adapter) 클래스

- 리스너의 모든 메소드가 단순 리턴하도록 구현해놓은 클래스

- 리스너 인터페이스를 상속받아 이벤트 리스너를 구현할 때 리스너 인터페이스의 메소드를 모두 구현해야 하는 부담 존재

- 이벤트 리스너 구현에 따른 부담 해소를 위해, 자바의 JDK에서 리스너 인터페이스를 미리 구현해 놓은 클래스를 제공하는데 이것이 어댑터 클래스

- 추상 메소드가 하나뿐인 리스너는 어댑터 클래스없음   ex)ActionAdapter, ItemAdapter 클래스는 존재하지 않음

 

ex) MouseAdapter

 

 

 

▷JDK에서 제공하는 어댑터 클래스

 

 

 

예제 5) 어댑터 사용(MouseAdapter)

 

 

예제 6) MouseAdapter를 사용하여 예제 4 수정

 

 

 

 

 

 

 

 

 

 

▶Key 이벤트와 포커스

● 키 입력 시, 다음 3가지 경우에 Key 이벤트 발생

1) 키를 누르는 순간

2) 누른 키를 떼는 순간

3) 누른 키를 떼는 순간(Unicode키의 경우에만)

 

 

● 키 이벤트를 받을 수 있는 조건

- 모든 컴포넌트가 가능하지만, 현재 포커스(focus)를 가진 컴포넌트

- 어떤 컴포넌트에서 키를 입력하고자 하면 <Tab>키나 마우스 클릭으로 포커스를 그 컴포넌트에게 이동해야 함

 

 

● 포커스(focus)

- 컴포넌트나 응용프로그램이 키 이벤트를 독점하는 권한

- 컴포넌트 포커스 설정 방법: 다음 2라인의 코드 필요

(자바 플랫폼마다 실행 환경의 초기화가 서로 다를 수 있기 때문에 다음 코드가 필요)

 

 

▷컴포넌트에 포커스 주기

- 키 입력을 받기 위해서 포커스를 주는 시점 또한 중요

 

 

1) 스윙 프레임이 만들어질 때, 포커스를 주고자 하는 경우

- JFrame의 setVisible(true) 이후에 포커스를 주어야 함

 

2) 마우스로 컴포넌트를 클릭하면, 그때 컴포넌트가 포커스를 얻고록 하는 경우

- 언제든지 필요할 때 포커스를 줄 수 있음

 

 

 

 

▷KeyListener의 메소드와 키

● KeyListener의 3개 메소드 

 

 

● 컴포넌트에 키 이벤트 리스너 등록

 

 

 

● 키는 2가지 종류 

1) 유니코드 키

- 유니코드는 전 세계의 문자에 대한 코드 체계

- 유니코드는 한글, 영어 등 세계 여러 나라들의 문자들에 대해 코드 값을 정의   ex) A~Z, a~z, 0~9, !, @, & 등

 

 

 

2) 유니코드가 아닌 키

- 문자 키가 아닌 제어 키  ex) <Function>, <Home>, <Up>, <Delete>, <Control>, <Shift>, <Alt> 등

- 정의된 유니코드 값 없음

- 키 마다 키 코드 값(가상 키 코드 값)이 정의되어 있음

- 유니코드 키가 아닌 경우 키 이벤트 호출 순서 :keyPressed(), keyReleased()만 호출됨

 

 

○ 가상 키(Virtual Key)

- 유니코드 키든 아니든 모든 키에 자바의 가상 키 코드가 정의되어 있음

- 가상 키 값으로 어떤 키인지 비교 판단 가능

- 가상 키 코드는 KeyEvent 클래스에 상수로 선언

 

 

 

 

▷ 입력된 키 판별

- 키가 입력되면 키 정보를 가진 이벤트 객체 생성(KeyEvent 객체)

- KeyEvent 객체가 리스너에 전달됨

 

 

1) 키의 문자 코드(유니코드) 알아내기 - char KeyEvent.getKeyChar()

- 눌러진 키에 해당하는 문자 코드(유니코드) 리턴

- 눌러진 키가 문자 키인 경우에만 작동

 

 

2) 입력된 키의 가상 키 값 알아내기 -  int KeyEvent.getKeyCode()

- 모든 키에 대해 작동

- 키 코드는 운영체제나 하드웨어에 따라 서로 다를 수 있기 때문에

- 입력된 키를 판별하기 위해 getKeyCode()가 리턴한 키 코드와 가상 키 값을 비교 (가상 키 값은 KeyEvent 클래스의 상수로 정의됨)

 

 

3) 키 이름 문자열 리턴 - String KeyEvent.getKeyText(int keyCode)

- Static 메소드

- 매개변수 keyCode의 코드 값(가상 키)에 해당하는 키의 이름 문자열 리턴

ex) F1 키의 경우 "F1", Shift 키의 경우 "SHIFT" 등의 문자열 리턴

 

 

 

예제 1) 다양한 KeyEvent와 KeyListener 활용

 

 

 

 

 

제 2)  <F1> 키를 입력받으면 컨텐트팬의 배경을 초록색으로, %키를 입력받으면 노란색으로 변경

 

 

 

 

제 3)  상, 하, 좌, 우 키로 "HELLO" 문자열을 마음대로 움직이기

 

 

 

 

 

▷마우스 이벤트와 마우스 관련 리스너

● 마우스 이벤트

- 사용자의 마우스 조작에 따라 발생하는 이벤트, 8가지 경우

 

 

● 마우스가 눌러진 위치에서 떼어지는 경우 메소드 호출 순서

 

 

● 마우스가 드래그될 때 호출되는 경우 메소드 호출 순서

 

 

 

▷ 마우스 리스너 달기

MouseListener의 5개 이벤트를 처리하는 경우

- mouseEntered(), mouseExited(), mousePressed(), mouseReleased(), mouseClicked()

 

○ 마우스 리스너 등록

- componet.addMouseListener(myMouseListener);

 

 

 

 

 MouseMotionListener의 이벤트도 함께 처리하고자 하는 경우

- mouseDragged(), mouseMoved()

 

○ 마우스 모션 리스너 등록 필요

- component.addMouseMotionListener(myMouseMotionListener);

 

 

 

 

▷MouseEvent 객체로부터 얻을 수 있는 정보

● 마우스 포인터의 위치

- int getX(), int getY()

- Point getPoint()

 

 

 

● 입력된 마우스 버튼

- int getButton()

 

 

 

● 마우스 클릭 횟수

-  int getClickCount()

 

 

예제) 마우스와 마우스 모션 이벤트 활용

 

 

 

 

예제) 더블클릭 시 컨텐트팬의 배경색 변경

 

 

 

 

 

▷MouseWheelEvent와 MouseWheelListener

마우스 휠 이벤트

- 마우스 휠이 구를 때 마다 발생하는 이벤트

- 이벤트 발생시마다 MouseWheelEvent 객체 생성

 

 

MouseWheelListener

- 마우스 휠 이벤트 리스너

- 마우스 휠 이벤트가 발생할 때 마다 호출되는 메소드

 

 

  마우스 휠 리스너 구현

 

 

 

 

 

 

'[Java]' 카테고리의 다른 글

[Java] 자바 GUI  (3) 2023.11.09
[Java] 컬렉션  (2) 2023.11.03
[Java] 자바의 문자열 다루기  (0) 2023.01.05
[Java] 자바의 주요 클래스  (0) 2023.01.04
[Java] 패키지, 모듈  (1) 2023.01.03

댓글