안녕, 세상!

7. 이벤트 프로그래밍 (1) 본문

It공부/Java

7. 이벤트 프로그래밍 (1)

dev_Lumin 2020. 7. 13. 08:20

(1) 이벤트의 개요

이벤트(Event)란 프로그램과 사용자간의 상호 작용을 위해서 사용자 키보드나 마우스 등의 장치를 통해서 응용 프로그램에 어떠한 요구를 하는 동작을 말합니다.

이벤트 소스는 이러한 이벤트를 발생시킬 수 있는 입력 장치를 말하며 예시로 키보드와 마우스 등이 있습니다.

이벤트가 발생하면 시스템에서 제공되는 이벤트 리스너가 해당 이벤트를 받아 처리하게 됩니다.

이벤트 리스너는 인터페이스 형식으로 제공됩니다.

 

특정 이벤트가 발생하면 해당하는 이벤트 리스너가 동작하여 해당 이벤트에 동작하도록 코딩되어 있는 이벤트 핸들러 메소드를 호출함으로써 동작을 실행합니다.

이벤트 핸들러는 프로그래머가 코딩하여 구현하도록 되어 있습니다.

 

① 이벤트의 종류

모든 이벤트 클래스들은 java.util.EventObject 클래스를 상속받으며 java.awt.event 패키지에 구현되어 있습니다.

 

import java.awt.event.*               // 이벤트 처리가 필요한 모든 프로그램에 포함

import javax.swing.event.*           // Swing 이벤트를 다루는 프로그램에 포함

 

 

 

② 이벤트 리스너(Event Listener)

이벤트 리스너는 시스템에서 제공되고 인터페이스(interface) 형태로 제공됩니다.

사용자는 이벤트를 처리하고자 하는 이벤트 리스너의 추상 메소드를 구현하여 코딩해야 합니다.

 

 

 

 

③ 이벤트 핸들러

이벤트 핸들러의 구현은 이벤트 리스너의 추상 메소드를 오버라이딩하여 구현함으로써 이루어집니다.

 

 

import javax.swing.*;

import java.awt.event.*;

import java.awt.*;

 

public class 클래스명 extends JFrame implements 리스너명,... 

{

   생성자( ) {          

       .....             // 윈도우 컴포넌트의 생성 및 배치

    }

    추상메소드( ) {     // 리스너 인터페이스의 추상 메소드 구현

       .....

    }

    public static void main(String [] args)  {

          클래스명 f = new 클래스명( );

    }

}

 

 

implements 로 인터페이스인 이벤트 리스너를 상속받습니다.

상속받은 리스너 인터페이스에 포함되어 있는 추상 메소드는 반드시 모두 구현해야 합니다. 

구현이 필요치 않은 추상 메소드가 있더라도 반드시 빈 메소드의 형태라도 구현해야 오류가 발생하지 않습니다.

 

 

 

 

 

(2) 마우스 이벤트

마우스로부터의 이벤트는 MouseListener 리스너를 이용하여 구현할 수 있습니다.

 

 

import javax.swing.*;

import java.awt.event.*;

import java.awt.*;

 

public class 클래스명 extends JFrame implements MouseListener {

    생성자( ) {

        ....     

        컴포넌트.addMouseListener(this);     // 윈도우 컴포넌트의 생성 및 배치

    }

    mousePressed(MouseEvent e) {           // 마우스가 눌러졌을 때 실행되는 메소드

        ....

    }

    mouseReleased(MouseEvent e) {         // 마우스가 떨어졌을 때 실행되는 메소드

        ....

    }

    mouseClicked(MouseEvent e) {            // 마우스가 클릭되었을 때 실행되는 메소드

        ....

    }

    mouseEntered(MouseEvent e) {           // 마우스가 들어왔을 때 실행되는 메소드

        ....

    }

    mosueExited(Mouse Event e) {            // 마우스가 나갔을 때 실행되는 메소드

        ....

    }

    public static void main(String [] args) {

        클래스명 f = new 클래스명( );

    }

}

 

 

 

마우스로부터 이벤트는 또한 MouseMotionListener 리스너 이용하여 이벤트 프로그로맹을 할 수 있습니다.

 

 

import javax.swing.*;

import java.awt.event.*;

import java.awt.*;

 

public class 클래스명 extends JFrame implements MouseListener {

    생성자( ) {

        ....     

        컴포넌트.addMouseListener(this);     // 윈도우 컴포넌트의 생성 및 배치

    }

    mouseDragged(MouseEvent e) {          // 마우스가 드래그될 때 실행되는 메소드

        ....

    }

    mouseMoved(MouseEvent e) {        // 마우스가 움직일 때 실행되는 메소드

        ....

    }

    public static void main(String [] args) {

        클래스명 f = new 클래스명( );

    }

}

    

 

다음은 MouseListener과 MouseMotionListener 리스너를 사용한 예시입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
public class mousesample extends JFrame implements MouseListener,MouseMotionListener{
    JLabel lb;
    JPanel pn;
    public mousesample() {
        setTitle("마우스 이벤트예제");
        setLayout(null);
        
        lb= new JLabel("마우스를 동작해보세요");
        pn= new JPanel();
        pn.setSize(400,200);
        pn.setBackground(Color.green);
        pn.setLocation(0,0);
        pn.add(lb);
        add(pn);
        pn.addMouseListener(this);
        pn.addMouseMotionListener(this);
        setSize(400,400);
        setVisible(true);
    }
    
    public void mousePressed(MouseEvent e) {
        lb.setText("마우스가 눌러졌습니다.");
    }
    public void mouseReleased(MouseEvent e) {
        lb.setText("마우스가 떨어졌습니다.");
    }
    public void mouseClicked(MouseEvent e) {
        lb.setText("마우스가 클릭되었습니다.");
    }
    public void mouseEntered(MouseEvent e) {
        lb.setText("마우스가 들어왔습니다.");
    }
    public void mouseExited(MouseEvent e) {
        lb.setText("마우스가 나갔습니다.");
    }
    public void mouseDragged(MouseEvent e) {
        lb.setText("마우스가 드래그됩니다 -> "+e.getX()+","+e.getY()); // 마우스의 위치 가져오기
    }
    public void mouseMoved(MouseEvent e) {
        lb.setText("마우스가 움직입니다 -> "+e.getX()+","+e.getY());
    }
    public static void main(String args[]) {
        mousesample ms = new mousesample();
    }
}
cs

마우스가 패널에서 나갔을 때
마우스가 패널에서 움질일 때

위의 코드는 초록색 패널에 마우스의 상태와 위치에 따라 라벨의 값이 다르게 출력되는 코드입니다.

다음 결과는 일부만 나타냈습니다. 이외에도 드래그나 클릭 모두 정상적으로 작동합니다.

 

 

 

 

 

(3) 키보드 이벤트

키보드로부터의 이벤트는 KeyListener 리스너를 이용하여 구현할 수 있습니다.

KeyListener에서 제공하는 메소드는 위의 표에 정리한대로 keyPressed(), keyReleased(), keyTyped() 메소드가 있습니다.

 

화면에 출력되는 키들은 KeyListener 리스너에서 제공하는 메소드가 모두 작동하지만, <F1>, <Ctrl>, <Shift>, <Alt>, <Esc>, 화살표 키 등 화면에 출력되지 않는 키를 누른 경우에는 keyPressed() 메소드와 keyReleased() 메소드만 출력됩니다.

 

 

import javax.swing.*;

import java.awt.event.*;

import java.awt.*;

 

public class 클래스명 extends JFrame implements keyListener {

    생성자( ) {

        ....     

        컴포넌트.addkeyListener(this);    // 컴포넌트에 키보드 이벤트 등록

    }

    keyPressed(keyEvent e) {         // 키를 누르는 순간 실행되는 메소드

        ....

    }

    keyReleased(keyEvent e) {       // 누른 키를 뗄 때 실행되는 메소드

        ....

    }

    keyTyped(KeyEvent e) {           // 일반 문자 키를 눌렀다가 뗄 때 실행되는 메소드

        ....

    }   

    public static void main(String [] args) {

        클래스명 f = new 클래스명( );

    }

}

 

 

입력된 키 값의 판별

입력된 키를 판별해주는 메소드는 일반 문자의 키의 경우에 getKeyChar() 메소드를 이용하면 해당 문자를 알 수 있고, 특수 키의 경우에는 getKeyCode() 메소드를 이용하면 해당 키의 코드 값을 알 수 있습니다.

getKeyChar() 메소드는 해당문자를 char 형태로 반환해주며, getKeyCode() 메소드는 해당문자를 int 형태의 데이터로 반환해줍니다.

 

특수 키의 코드 값은 KeyEvent 클래스에 정의되어 있으며, 다음과 같습니다.

 

다음은 키보드 이벤트를 이용한 예시입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
public class keysample1 extends JFrame implements KeyListener{
    JLabel lb;
    public keysample1() {
        setTitle("키보드 예제");
        setLayout(new FlowLayout());
        lb = new JLabel("키보드를 이용해서 키를 입력하시오.");
        add(lb);
        addKeyListener(this);
        setSize(400,400);
        setVisible(true);    
    }
    public void keyPressed(KeyEvent e) {
        lb.setText("키가 눌러졌습니다: "+e.getKeyText(e.getKeyCode()));
    }
    public void keyReleased(KeyEvent e) {
        lb.setText("키가 떼어졌습니다: "+e.getKeyText(e.getKeyCode()));
    }
    public void keyTyped(KeyEvent e) {
        lb.setText("문자키가 입력되었습니다: "+e.getKeyChar());
    }
    public static void main(String [] args) {
        keysample1 ks = new keysample1();
    }
}
cs

위의 코드 결과의 일부만 나타냈습니다.

키를 누른상태에서는 "키가 눌러졌습니다" 라고 나오고 해당 키의 값이 소문자로 나옵니다.

특수 키는 특수키 코드를 텍스트로 출력시키게 설정해 놓아서 다음과 같이 잘 나옵니다.

 

 

다음은 또다른 예시입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
public class keysample extends JFrame implements KeyListener{
    JButton bt;
    public keysample() {
        setTitle("키보드 예제");
        setLayout(null);
        setSize(400,200);
        bt = new JButton("자유로운 버튼");
        bt.setLocation(60,30);
        bt.setSize(110,30);
        add(bt);
        addKeyListener(this);
        setVisible(true);
        requestFocus();  // 키 이벤트를 받을 컴포넌트를 강제로 설정
    }
    public void keyPressed(KeyEvent e) {
        int keyCode = e.getKeyCode();
        switch(keyCode) {
        case KeyEvent.VK_UP:   // 위 방향키를 누르면 위로 20픽셀 이동
            bt.setLocation(bt.getX(),bt.getY()-10);
            break;
         
        case KeyEvent.VK_DOWN: // 아래 방향키를 누르면 아래로 20픽셀 이동
            bt.setLocation(bt.getX(),bt.getY()+10);
            break;
        
        case KeyEvent.VK_LEFT:  // 왼쪽 방향키를 누르면 왼쪽으로 20픽셀 이동
            bt.setLocation(bt.getX()-10,bt.getY());
            break;
        
        case KeyEvent.VK_RIGHT:  // 오른쪽 방향키를 누르면 오른쪽으로 20픽셀 이동
            bt.setLocation(bt.getX()+10,bt.getY());
            break;
        
        case KeyEvent.VK_F1:
            bt.setBackground(Color.gray);
            break;
        }
    }
    public void keyReleased(KeyEvent e) {}
    public void keyTyped(KeyEvent e) {}
    public static void main(String [] args) {
        keysample s = new keysample();
    }
}
cs

 

방향키를 누를 때 해당 방향으로 버튼이 10픽셀 만큼 움직입니다.

16줄의 requestFocus(); 를 꼭 써야 키 이벤트가 발생하게 됩니다.

 

키 이벤트는 포커스가 위치해 있어야 키 이벤트가 발생하기 때문에  강제로 포커스를 설정해줍니다.

requestFocus();   

하지만 포커스 받을 컴포넌트가 여러개 있을 경우에는 우선적으로 포커스 받을 컴포넌트를 설정합니다.

컴포넌트.setFocusable(true);

 

 

 

 

어댑터(Adapter) 클래스

리스너 인터페이스를 사용할 경우 해당하는 리스너 인터페이스의 모든 추상 메소드를 구현해야한다고 위에서 설명했습니다.

추상 메소드중 하나만 필요한 경우에도 구현할 필요가 없는 추상 메소드를 구현하는 부담을 줄이기 위해서 자바에서는 어댑터 클래스를 제공합니다.

어댑터 클래스는 리스너 인터페이스의 모든 메소드가 단순 리턴하도록 미리 구현해놓은 클래스로 필요한 메소드만 구현해서 사용할 수 있습니다.

그러나 모든 리스너가 어댑터 클래스를 제공하는 것은 아닙니다.

 

어댑터 적용시 어댑터는 다음과 같이 적용하면 됩니다.

다음 예시는 MouseListener 인터페이스를 어댑터로 사용하는 예시입니다.

 

import javax.swing.*;

import java.awt.event.*;

import java.awt.*

 

public class 클래스명 extends JFrame implements MouseListener {

    생성자 ( ) {

    .... 

    addMouseListener(new 어댑터명( ));

    ....

    }

    class 어댑터명 extends MouseAdapter {

        public void 사용할추상메소드명(MouseEvent e) {  //MouseListner 인터페이스 중 사용할 메소드들만 구현 

            ....

        }           

        ....                                       

    }

    public static void main(String [ ] args) {

    ....

    }

}

 

 

'It공부 > Java' 카테고리의 다른 글

8. 그래픽  (0) 2020.07.15
7. 이벤트 프로그래밍 (2)  (0) 2020.07.14
6. 윈도우 프로그래밍  (0) 2020.07.12
5. 클래스 상속  (0) 2020.07.11
4. 클래스와 객체  (0) 2020.07.10
Comments