▷ 사용자가 UI의 컴포넌트를 사용하는 순간 이벤트가 발생, 프로그램은 이벤트를 처리하기 위해 코드를 실행함
▷ 위임형 방식 : 이벤트가 발생하면 직접 처리하지 않고 소스에 추가된 리스너에게 이벤트 처리를 위임하는 방식
▷ 동시에 여러 개의 이벤트가 발생하기도 함.
◎ 대표적 이벤트 및 이벤트 처리 리스너
NO
이벤트 소스
발생 이벤트
발생 원인
리스너
1
JFrame
WindowEvent
중 하나를 클릭했을 때
WindowListene
2
JDialog
WindowEvent
중 하나를 클릭했을 때
WindowListene
3
JTextField
ActionEvent
Enter 키를 눌렀을 때
ActionListener
4
JButton
ActionEvent
클릭했을 때
ActionListener
5
JRadioButton
ActionEvent
클릭했을 때
ActionListener
6
JCheckBox
ActionEvent
클릭했을 때
ActionListener
7
JMenuItem
ActionEvent
선택했을 때
ActionListener
8
JComboBox
ActionEvent
다른 항목을 선택했을 때
ActionListener
9
JList
ListSelectionEvent
다른 항목을 선택했을 때
ListSelectionListener
(1) Listener와 Adapter
▷ 리스너 클래스를 생성하는 방법은 리스너 인터페이스를 구현하는 방법과 어댑터 클래스를 상속하는 방법이 있음
◎ 리스너 인터페이스 구현 방법
class MyWindowListener implements WindowListener {
public void windowActivated(WindowEvent e) {}
public void windowClosed(WindowEvent e) {}
public void windowClosing(WindowEvent e) {
//닫기(x) 버튼을 클릭했을 때 처리 방법 코딩
}
public void windowDeactivated(WindowEvent e) {}
public void windowDeiconified(WindowEvent e) {}
public void windowIconified(WindowEvent e) {}
public void windowOpened(WindowEvent e) {}
}
닫기 버튼에서 발생하는 WindowEvent만 처리하고 싶어도 windowClosing() 및 나머지 6개를 위와 같이 재정의 해야함
◎ 리스너 어댑터를 상속하는 방법
▷ 리스너 어댑터를 상속하면 관심 있는 이벤트 처리 메소드만 재정의할 수 있기 때문에 리스너 인터페이스를 구현하는 방법보다 좀 더 효율적임
▷ WindowAdapter 클래스를 상속할 경우 windowClosing() 메소드만 재정의하면 됨
▶ 나머지 6개의 메소드는 WindowAdapter에서 내용이 없는 채로 이미 구현되어 있음
▷ 리스너 인터페이스에 대응되는 어댑터 클래스가 모두 존재하는 것은 아님
▷ 리스너 인터페이스에 2개 이상의 이벤트 처리 메소드가 정의되어 있을 경우에만 어댑터 클래스가 제공됨
◎ 리스너 인터페이스와 대응되는 어댑터 클래스
NO
리스너 인터페이스
어댑터
1
java.awt.event.WindowListener
java.awt.event.WindowAdapter
2
java.awt.event.MouseListener
java.awt.event.MouseAdapter
3
java.awt.event.KeyListener
java.awt.event.KeyAdapter
4
java.awt.event.ActionListener
없음
5
javax.swing.event.ListSelectionListener
없음
◎ 제목 표시줄 닫기(x)버튼(JFrame), btnClose 버튼(하단)을 이용한 프로그램 종료 예제
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class ClosableExample1 extends JFrame {
private JButton btnClose;
// 메인 윈도우 설정
public ClosableExample1() {
this.setTitle("CloseExample");
this.setSize(300, 100);
this.setLayout(new FlowLayout());
this.getContentPane().add(getBtnClose());
// WindowListener 추가
this.addWindowListener(new MyWindowAdapter());
}
// 닫기 버튼 생성
private JButton getBtnClose() {
if(btnClose == null) {
btnClose = new JButton();
btnClose.setText("닫기");
// ActionListener 추가
btnClose.addActionListener(new MyActionListener());
}
return btnClose;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
ClosableExample1 jFrame = new ClosableExample1();
jFrame.setVisible(true);
}
});
}
// WindowAdapter 클래스를 상속해서 WindowListener 클래스 작성
// 윈도우 창의 닫기 X 버튼
class MyWindowAdapter extends WindowAdapter{
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
// WindowAdapter 클래스를 상속해서 WindowListener 클래스 작성
class MyActionListener implements ActionListener{
@Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
}
}
출력 창
◎Anonymous Listener
▷ 이벤트를 처리할 때 리스너 클래스를 외부 클래스로 선언하면 컨테이너의 필드와 메소드에 접근하는 것이 불편함
▶ 리스너는 일반적으로 익명(Anonymous) 객체로 작성함
◎ 익명 객체를 이용한 프로그램 종료 예제
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class ClosableExample2 extends JFrame {
private JButton btnClose;
// 메인 윈도우 설정
public ClosableExample2() {
this.setTitle("CloseExample");
this.setSize(300, 100);
this.setLayout(new FlowLayout());
this.getContentPane().add(getBtnClose());
// 익명 WindowListener 객체 추가
this.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
// 닫기 버튼 생성
private JButton getBtnClose() {
if(btnClose == null) {
btnClose = new JButton();
btnClose.setText("닫기");
// 익명 ActionListener 추가
btnClose.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
}
return btnClose;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
ClosableExample2 jFrame = new ClosableExample2();
jFrame.setVisible(true);
}
});
}
}
메소드만 따로 만들지 않고 익명 객체를 작성해도 위와 동일한 출력이 나타납니다.
▷복수 개의 컴포넌트에서 동일한 리스너를 사용해서 이벤트를 처리하고 싶다면 리스너를 필드로 선언
◎ 두 개의 JButton에서 발생하는 ActionEvent를 하나의 ActionListener 익명 객체로 처리하는 예제
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class ActionListenerExample extends JFrame {
private JButton btnOk;
private JButton btnCancel;
// 메인 윈도우 설정
public ActionListenerExample() {
this.setTitle("ActionListenerExample");
this.setSize(300, 100);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLayout(new FlowLayout());
this.getContentPane().add(getBtnOk());
this.getContentPane().add(getBtnCancel());
}
// ActionListener 타입의 필드 선언 및 익명 객체로 초기화
private ActionListener actionListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// ActionEvent가 발생한 컴포넌트 구분
if(e.getSource() == btnOk) {
System.out.println("확인 버튼을 클릭했습니다.");
} else if(e.getSource() == btnCancel) {
System.out.println("취소 버튼을 클릭했습니다.");
}
}
};
// Ok 버튼 생성
private JButton getBtnOk() {
if(btnOk == null) {
btnOk = new JButton();
btnOk.setText("확인");
// actionListener 필드 대입
btnOk.addActionListener(actionListener);
}
return btnOk;
}
// Cancel 버튼 생성
private JButton getBtnCancel() {
if(btnCancel == null) {
btnCancel = new JButton();
btnCancel.setText("취소");
// actionListener 필드 대입
btnCancel.addActionListener(actionListener);
}
return btnCancel;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
ActionListenerExample jFrame = new ActionListenerExample();
jFrame.setVisible(true);
}
});
}
}
Listener와 Adapter을 이용해서 버튼 조작으로 닫기 버튼 조작을 가능할 수 있게 만들었습니다.