본문 바로가기

BackEnd/Java

[java]이것이 자바다 부록 Java UI 4 (Swing을 이용한 이벤트 처리)

728x90
반응형

1. 이벤트 처리

   ▷ UI 프로그램은 사용자와 상호작용을 하면서 코드를 실행함

   ▷ 사용자가 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을 이용해서 버튼 조작으로 닫기 버튼 조작을 가능할 수 있게 만들었습니다.

 

html, css, java script 했던 것과 비슷하네요ㅎㅎ

 

많은 분들의 피드백은 언제나 환영합니다!  많은 댓글 부탁드려요~~

 

728x90
반응형