최원종의 개발 블로그

Key Listener 본문

Java/SWING

Key Listener

chl6698 2026. 3. 17. 17:11

KeyListener 개념

사용자가 키보드를 조작할 때 발생하는 이벤트를 감지하는 리스너.

텍스트 입력 창에서 글자 수를 제한하거나, 게임에서 캐릭터를 움직일 때 필수적으로 사용.

 

KeyListener 3가지 규칙(추상 메서드)

  1. keyPressed(KeyEvent e): 키가 눌렸을 때(꾹 누르고 있으면 계속 호출 -> 게임 이동에 적합)
  2. keyReleasd (KeyEvent e):키에서 손을 뗐을 때(타이핑 검증에 적합)
  3. keyTyped(KeyEvent e): 문자가 입력되었을 때 (화살표, F1등 특수키는 무시됨)

코드

package swing.ch08;

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

/**
 *  KeyListener 인터페이스를 구현하여 키보드 이벤트를 처리하는 클래스를 설계
 *  1. JFrame 을 상속받아 창을 만들고
 *  2. KeyListener 를 구현하여 '감시자' 자격을 갖춤
 */
public class KeyEventListenerFrame extends JFrame implements KeyListener {

    private final int FREAM_SIZE = 500;
    private JTextArea textArea;

    public KeyEventListenerFrame() {
        initData();
        setInitLayout();
        addEventListener();
    }

    private void initData() {
        setSize(FREAM_SIZE, FREAM_SIZE);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setResizable(false); // 사용자가 마우스 크기로 창 크기를 조절 못하게 고정하는 옵션

        textArea = new JTextArea();
    }

    private void setInitLayout() {
        setLayout(new BorderLayout()); // 전체 기본 레이아웃
        add(textArea);
        setVisible(true);
    }

    private void addEventListener() {
        // 핵심 개념
        // textArea 에게 키보드 입력이 들어보면 this(나)한테 알려줘 라고 등록하는 과정
        textArea.addKeyListener(this);
    }


    // ---------------- KeyListener 추상 메서드를 일반 메서드로 재정의 (구현)
    // 문자가 입력되었을 때 호출
    @Override
    public void keyTyped(KeyEvent e) {
        //System.out.println("keyTyped 호출 됨");
    }

    // 키보드의 어떤 키든 눌렀을 때 호출
    @Override
    public void keyPressed(KeyEvent e) {
        // System.out.println(e.getSource() + " : 주소값");
        System.out.println(e.getKeyCode() + " : 키 코드");
        // 콘솔창에 화살표 뭐가 눌러 졌는지 구분해 보기
        if(e.getKeyCode() == KeyEvent.VK_LEFT) {
            System.out.println("왼쪽 화살표 이벤트 발생");
        } else if(e.getKeyCode() == KeyEvent.VK_UP) {
            System.out.println("위쪽 화살표 이벤트 발생");
        } else if(e.getKeyCode() == KeyEvent.VK_RIGHT) {
            System.out.println("오른쪽 화살표 이벤트 발생");
        } else if(e.getKeyCode() == KeyEvent.VK_DOWN) {
            System.out.println("아래 화살표 이벤트 발생");
        }
    }

    // 어떤 키든 손을 뗐을 때 호출
    @Override
    public void keyReleased(KeyEvent e) {
        //System.out.println("keyReleased 호출 됨");
    }


    // 테스트 코드 - 메인쓰레드
    public static void main(String[] args) {
        new KeyEventListenerFrame();
    }
}

-별 움직이기 코드

package innerclass.swing.ch08;

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

//키 리스너를 구현하여 키보드 입력을 받아서 라벨을 움직이는 클래스
public class MoveCharFrame extends JFrame implements KeyListener {
    private JLabel label;
    private int count = 0;

    private final int MOVE_STEP = 10;
    private final int INIT_X = 225;
    private final int INIT_Y = 200;
    private final int FRAME_SIZE = 500;

    public MoveCharFrame() {
        initData();
        setInitLayout();
        addEventListener();
    }

    private void initData() {
        setTitle("방향키로 별 움직이기 실습");
        setSize(FRAME_SIZE, FRAME_SIZE);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setResizable(true);

        label = new JLabel("★");
        label.setFont(new Font("맑은 고딕", Font.BOLD, 30));//폰트 설정
        label.setSize(50, 50);// 라벨 자체의 크기
        label.setLocation(INIT_X, INIT_Y);//초기 시작 위치 (중앙 부근)
    }

    private void setInitLayout() {
        //중요
        setLayout(null); //좌표로 직접 움직이기 위해 기본 레이아웃을 제거 합니다.
        add(label);
        setVisible(true);
    }

    private void addEventListener() {
        //1. 프레임에 키 리스너르 등록(나 자신을 리스너로 임명)
        this.addKeyListener(this);

        //필수
        //키보드 이벤트를 받기 위해 프레임이 포커스를 가질 수 있게 합니다.
        this.setFocusable(true);
        this.requestFocusInWindow();
    }

    //키 리스너 추상 메서드 구현
    @Override
    public void keyTyped(KeyEvent e) {

    }

    @Override
    public void keyPressed(KeyEvent e) {
        int KeyCode = e.getKeyCode();
        int x = label.getX();//현재 자신의 x 좌표값을 반환
        int y = label.getY();//현재 자신의 x 좌표값을 반환

        //방향키 코드값에 따라 새로운 좌표 설정
        if (KeyCode == KeyEvent.VK_LEFT) {
            label.setLocation(x - MOVE_STEP, y);
        } else if (KeyCode == KeyEvent.VK_UP) {
            label.setLocation(x, y - MOVE_STEP);

        } else if (KeyCode == KeyEvent.VK_RIGHT) {
            label.setLocation(x + MOVE_STEP, y);


        } else if (KeyCode == KeyEvent.VK_DOWN) {
            label.setLocation(x, y + MOVE_STEP);

        } else if (KeyCode == KeyEvent.VK_ESCAPE) {
            label.setLocation(INIT_X, INIT_Y);
        }
        count++;
        setTitle("방향키로 별 움직이기 실습 | 이동 횟수: " + count);
        label.setText("★");
    }

    @Override
    public void keyReleased(KeyEvent e) {
        label.setText("☆");
    }

    static void main() {
        new MoveCharFrame();
    }//end of main
}

KeyListener 등록 패턴 3가지

1. implements

public class MyFrame extends JFrame implements KeyListener {
    // 메서드 직접 오버라이드
    component.addKeyListener(this); // this = 이 클래스 자체가 리스너
}

 

2. 익명 클래스

component.addKeyListener(new KeyListener() {
    @Override
    public void keyPressed(KeyEvent e) { /* ... */ }
    @Override
    public void keyReleased(KeyEvent e) { /* ... */ }
    @Override
    public void keyTyped(KeyEvent e) { /* ... */ }
});

 

3.KeyAdapter()

// KeyAdapter는 KeyListener의 추상 클래스 버전
// → 필요한 메서드만 오버라이드 가능!
component.addKeyListener(new KeyAdapter() {
    @Override
    public void keyPressed(KeyEvent e) {
        // 필요한 것만 구현, 나머지 빈 메서드 불필요
    }
});

어댑터 클래스 구현

package swing.ch08;

public interface SmartHomeListener {
    public abstract void onPowerOn();
    public abstract void onPowerOff();
    public abstract void onTemperatureChange(int t);
}

 

package swing.ch08;

public abstract class SmartHomeListenerAdapter implements SmartHomeListener {

    @Override
    public void onPowerOn() {}

    @Override
    public void onPowerOff() {}

    @Override
    public void onTemperatureChange(int t) {}
}

 

-SmartHome

package swing.ch08;

public class SmartHome {

    public static void main(String[] args) {

        // 1. 인터페이스를 직접 구현할 때 (지저분함)
        // 익명 클래스 활용
        SmartHomeListener homeListener1 = new SmartHomeListener() {
            @Override
            public void onPowerOn() {

            }

            @Override
            public void onPowerOff() {

            }

            @Override
            public void onTemperatureChange(int t) {

            }
        };

        // 2. 어댑터 추상 클래스를 사용할 때 (깔끔함!)
        SmartHomeListenerAdapter listenerAdapter = new SmartHomeListenerAdapter() {
            @Override
            public void onTemperatureChange(int t) {
                System.out.println("에어컨 가동 : 현재 온도 : " + t + "도 최적화 중....");
            }
        };

        // 사용해 보기
        listenerAdapter.onTemperatureChange(23);

    } // end of main
}

 

'Java > SWING' 카테고리의 다른 글

Swing (Thread 활용)  (0) 2026.03.18
JLable 사용해 이미지 겹치기  (0) 2026.03.17
이벤트 리스너(ActionListener)  (0) 2026.03.16
패널 만들어 보기  (0) 2026.03.09
좌표값으로 컴포넌트 배치  (0) 2026.03.09