[Day +29]이벤트 & 미니 프로젝트 1일차
210802 월
<이벤트>
1. 이벤트 기반 프로그래밍
-이벤트의 발생에 의해 프로그램 흐름이 결정
-이벤트가 발생하면 이벤트를 처리하는 루틴(이벤트 리스너)이 실행
2. 이벤트 종류
1) 사용자의 입력 : 마우스 드래그, 마우스 클릭, 키보드 누름 등
2) 센서의 입력, 네트워크로부터 데이터 송수신
3) 다른 응용프로그램이나 다른 스레드로부터의 메시지
3. 이벤트 클래스 계층 구조
4. 이벤트 객체 포함 정보
1) 이벤트 종류 · 이벤트 소스
2) 이벤트가 발생한 화면 좌표
3) 이벤트가 발생한 컴포넌트 내 좌표
4) 버튼이나 메뉴 아이템에 이벤트가 발생한 경우, 버튼이나 메뉴 아이템의 문자열
5) 클릭된 마우스 버튼 번호
6) 마우스의 클릭 횟수
7) 눌러진 키의 코드 값과 문자 값
8) 체크박스, 라디오버튼 등과 같은 컴포넌트에 이벤트 발생시, 체크 상태
5. 이벤트 리스너(리스너는 이벤트를 여러개 갖고 있음)
1) 클래스로 작성된 이벤트를 처리하는 코드
2) 이벤트 처리를 위해서는 이벤트 발생을 시킬 컴포넌트에 이벤트 리스너를 연결해야 함
3) JDK에서 이벤트 리스너 작성을 위한 인터페이스를 제공
6. 어댑터(Adapter) 클래스
리스너 인터페이스의 추상 메소드를 모두 구현해야 하는 부담을 줄이기 위해 제공된 클래스 리스너의 모든 메소드가 단순 리턴하도록 구현한 클래스
<리스너와 어댑터>
7. 리스너 연결
컴포넌트 객체에 지정된 이벤트 리스너를 연결하면, 이벤트 리스너가 해당 이벤트를 감지하고 자동으로 이벤트 처리 객체로 연결되어 이벤트가 발생한 객체의 정보를 넘김
예) 컴포넌트레퍼런스.add이벤트명Listener(이벤트핸들러);
8. 이벤트 처리용 클래스 작성 방법
1) 무명(익명) 클래스로 작성
2) 별도의 클래스로 작성
3) 내부(Inner) 클래스로 작성
4) 프레임 구성 클래스에 인터페이스 상속하여 작성
<Part01_mouseAndKeyboardEvent>
1) MouseEvent
package com.kh.event.part01_mouseAndKeyboardEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
//Mouse Event : 마우스가 클릭 될 때, 눌릴 때, 뗄 때, 다시 쓰기
//Mouse .. 다시 쓰기
//해당 프레임 클래스에서 리스너 상속 받아 메소드 오버라이딩
public class A_MouseEvent extends JFrame implements MouseListener, MouseMotionListener {
public A_MouseEvent() {
this.setTitle("Mouse Event");
this.setSize(300, 200);
JPanel panel = new JPanel();
//컴포넌트.이벤트감지기(이벤트 핸들러)
panel.addMouseListener(this);
panel.addMouseMotionListener(this);
this.add(panel);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
public static void main(String[] args) {
new A_MouseEvent();
}
//출력용 메소드 먼저 선언
public void display(String msg, MouseEvent e) {
System.out.println(msg + " X = " + e.getX() + " Y = " + e.getY());
}
@Override //마우스를 클릭할 때(마지막)
public void mouseClicked(MouseEvent e) {
display("Mouse Clicked", e);
}
@Override //마우스를 눌렀을 때
public void mousePressed(MouseEvent e) {
display("Mouse Pressed", e);
}
@Override //마우스를 뗐을 때
public void mouseReleased(MouseEvent e) {
display("Mouse Released", e);
}
@Override
public void mouseEntered(MouseEvent e) {
display("Mouse Entered", e);
}
@Override
public void mouseExited(MouseEvent e) {
display("Mouse Exited", e);
}
@Override
public void mouseDragged(MouseEvent e) {
display("Mouse Dragged", e);
}
@Override
public void mouseMoved(MouseEvent e) {
display("Mouse Moved", e);
}
}
2) KeyEvent
package com.kh.event.part01_mouseAndKeyboardEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JTextField;
public class B_KeyEvent extends JFrame implements KeyListener {
public B_KeyEvent() {
this.setTitle("Key Event");
this.setSize(300, 20);
JTextField tf = new JTextField(20);
tf.addKeyListener(this);
this.add(tf);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
public static void main(String[] args) {
new B_KeyEvent();
}
//출력용 메소드
public void display(String msg, KeyEvent e) {
//눌러진 키에 해당하는 문자 값
char c = e.getKeyChar();
//눌러진 키에 대한 정수형인 키 코드 값
int keyCode = e.getKeyCode();
//Alt, Ctrl, Shift 판별
String modifies = e.isAltDown() + " " + e.isControlDown() + " " + e.isShiftDown();
System.out.println(msg + " c : " + c + " keyCode : " + keyCode);
System.out.println(modifies);
}
//유니코드 키가 입력 된 경우에만 동작함
@Override
public void keyTyped(KeyEvent e) {
display("Key Typed : ", e);
}
@Override
public void keyPressed(KeyEvent e) {
display("Key Pressed : ", e);
}
@Override
public void keyReleased(KeyEvent e) {
display("Key Released : ", e);
}
}
<Part02_howToUse>
1) AnomynusClassTest
package com.kh.event.part02_howToUse;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
//자바 GUI 이벤트 처리 (event handling) 구현
//
public class A_AnomynusClassTest {
public static void main(String[] args) {
JFrame mf = new JFrame("익명클래스");
mf.setSize(300, 200);
JPanel panel = new JPanel();
JButton button = new JButton("버튼을 눌러보세요");
JLabel label = new JLabel("아직 버튼이 눌려지지 않았습니다");
//익명 클래스란 이름을 가지지 않는 클래스
//클래스의 선언과 동시에 객체를 생성. 단 하나의 객체만을 생성하는 일회용 클래스.
//생성자 선언 불가. 오직 단 하나의 클래스나 단 하나의 인터페이스를 상속 받거나 구현함
//구현해야 하는 메소드가 매우 적은 클래스를 구현할 때 사용함. 재사용 불가.
button.addMouseListener(new MouseAdapter() {
//Listener -> Interface -> 추상 메소드만 가지고 있음
//Adapter -> abstract class -> Listener를 내용 없이 구현한 추상 클래스
// *Listener 구현 시 오버라이딩할 필요 없는 메소드가 있담면
// Adapter 상속 시 구현하지 않아도 됨
@Override
public void mouseClicked(MouseEvent e) {
label.setText("드디어 버튼이 눌러졌습니다.");
}
});
panel.add(button);
panel.add(label);
mf.add(panel);
mf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mf.setVisible(true);
}
}
2) OtherClassTest
package com.kh.event.part02_howToUse;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
//자바 GUI 이벤트 처리(event handling) 방법2
//별도의 외부 클래스로 작성하고 참조해서 사용
public class B_OtherClassTest extends JFrame {
public B_OtherClassTest() {
this.setSize(300, 200);
this.setTitle("외부클래스");
JPanel panel = new JPanel();
JButton button = new JButton("버튼을 눌러보세요");
JLabel label = new JLabel("아직 버튼이 눌려지지 않았습니다");
//이벤트 핸들링 시 별도의 외부 클래스 객체 전달
button.addMouseListener(new MyEvent(label));
panel.add(button);
panel.add(label);
this.add(panel);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
public static void main(String[] args) {
new B_OtherClassTest();
}
}
//바깥 영역은 무조건 default로 적어줘야 한다. public클래스는 지정한 클래스 명과 같아야 하기 때문
class MyEvent extends MouseAdapter{
private JLabel label;
public MyEvent(JLabel label) {
this.label = label;
}
@Override
public void mouseClicked(MouseEvent e) {
label.setText("드디어 버튼이 눌려졌습니다.");
}
}
3) InnerClassTest
package com.kh.event.part02_howToUse;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
//자바 GUI 이벤트 처리(event handling) 방법3
//내부 클래스에 리스너/어댑터 구현/상속 후 메소드 오버라이딩
public class C_InnerClassTest extends JFrame {
/*
* 내부 클래스는 클래스 안에 선언된 클래스로
* 내부 클래스에서 외부 클래스의 멤버에 쉽게 접근 가능
* 특정한 클래스에서만 사용 되는 클래스일 때 내부 클래스로 작성
*/
private JPanel panel;
private JLabel label;
private JButton button;
public C_InnerClassTest() {
this.setSize(300, 200);
this.setTitle("내부 클래스");
panel = new JPanel();
button = new JButton("버튼을 눌러보세요");
label = new JLabel("아직 버튼이 눌려지지 않았습니다");
//이벤트 핸들링 시 내부 클래스 객체 전달
button.addActionListener(new MyEvent());
panel.add(button);
panel.add(label);
this.add(panel);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
//내부 클래스 선언(ActionListener 구현)
private class MyEvent implements ActionListener{
@Override
public void actionPerformed(ActionEvent e) {
label.setText("드뎌 버튼이 눌러졌습니다");
}
}
public static void main(String[] args) {
new C_InnerClassTest();
}
}
4) MethodTest
package com.kh.event.part02_howToUse;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
//자바 GUI 이벤트 처리(Event handling) 방법4
//해당 프레임 클래스에서 리스너 상속받아서 메소드 오버라이딩
public class D_MethodTest extends JFrame implements ActionListener {
private JPanel panel;
private JLabel label;
private JButton button;
public D_MethodTest() {
this.setSize(300, 200);
this.setTitle("클래스에서 구현");
panel = new JPanel();
button = new JButton("버튼을 눌러보세요");
label = new JLabel("아직 버튼이 눌려지지 않았습니다");
//이벤트 핸들링 시 클래스 내부에 구현된 메소드 사용
button.addActionListener(this);
panel.add(button);
panel.add(label);
this.add(panel);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
@Override
public void actionPerformed(ActionEvent e) {
label.setText("드디어 버튼이 눌려졌습니다");
}
public static void main(String[] args) {
new D_MethodTest();
}
}
<Part03_changePanel>
1) Common
ChangePanel
package com.kh.event.part03_changePanel.common;
import javax.swing.JPanel;
import com.kh.event.part03_changePanel.view.MainFrame;
public class ChangePanel {
public static void changePanel(MainFrame mf, JPanel op, JPanel np) {
//컨테이너(프레임)과 이전 패널(old panel), 새 패널(new panel)의 주소
//매개변수로 전달 받음
mf.remove(op); //old panel 지우기
mf.add(np); //new panel 올리기
mf.revalidate();
//레이아웃 관리자에게 새 구성요소로 재설정하도록(새롭게 올라간 컴포넌트가 보이게 하기 위해서)
mf.repaint(); //구성요소 다시 그리도록
}
}
2) View
(1) MainFrame
package com.kh.event.part03_changePanel.view;
import javax.swing.JFrame;
public class MainFrame extends JFrame {
public MainFrame() {
super("패널 체인지 테스트");
this.setSize(1080, 800);
new MainPage(this);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
}
(2) MainPage
package com.kh.event.part03_changePanel.view;
import java.awt.Color;
import java.awt.Label;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JPanel;
import com.kh.event.part03_changePanel.common.ChangePanel;
public class MainPage extends JPanel {
private MainFrame mf;
private JPanel mainPage;
public MainPage(MainFrame mf) {
this.mf = mf;
this.mainPage = this;
//패널 배경색 설정 & 라벨 글씨 추가
this.setBackground(Color.gray);
this.add(new Label("Main Page"));
//메인 페이지에서 클릭이 일어났을 때 이벤트 감지
this.addMouseListener(new MyMouseAdpater());
mf.add(this);
}
class MyMouseAdpater extends MouseAdapter{
@Override
public void mouseClicked(MouseEvent e) {
ChangePanel.changePanel(mf, mainPage, new SubPage());
}
}
}
(3) SubPage
package com.kh.event.part03_changePanel.view;
import java.awt.Color;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class SubPage extends JPanel{
public SubPage() {
//패널 배경 색상 설정 & 라벨 글씨 부착
this.setBackground(Color.yellow);
this.add(new JLabel("Sub Page"));
}
}
3) Run
package com.kh.event.part03_changePanel.run;
import com.kh.event.part03_changePanel.view.MainFrame;
public class Run {
public static void main(String[] args) {
new MainFrame();
}
}