이벤트가 발생함
이벤트가 발생하면 이벤트 객체가 생성됨
이벤트 리스너를 호출
이벤트 리스너 실행
이벤트 소스 : 이번 이벤트를 발생시킨 컴포넌트
이벤트 객체 : 이번에 발생한 이벤트에 대한 정보를 담은 객체
이벤트 리스너 : 이벤트를 처리하는, 즉 받아온 이벤트를 어떻게 동작시킬지에 대한 코드
이벤트 분배 스레드 : 이벤트에 대한 모든 동작을 수행하게 도와주는 놈
EventObject.getSource() : 어떤 컴포넌트에서 이벤트가 발생했는지 그에 해당하는 참조자를 리턴해줌
리스너 코드들은 항상 이벤트 객체를 받게 되어있다.
ex. try-catch 구문과 유사. try 에서 이벤트 객체를 던지면 catch 문에서, 즉 리스너 코드가 이벤트 객체를 받음.
매개변수 e 로 이벤트 객체를 받은 경우, e.getSource() 로 어떤 컴포넌트에서 이벤트가 발생했는지 그에 해당하는 참조자를 리턴해줌
리턴타입 : Object => 실제 사용시에 캐스팅을 해서 사용할것!
이벤트 객체종류
ex. 버튼을 클릭했을 때 그 버튼한테 등록된 MouseEvent 이벤트 리스너를 찾아서, 그 리스너 안쪽에다 화면에 변경되는 내용을 작성하면 된다.
ex. ActionListener 인터페이스
interface ActionListener{ // 아래 메소드를 개발자가 구현해야함
public void actionPerformed(ActionEvent e); // => 이 메소드 하나만 재정의 해주면 된다.
}
ex. MouseListener 인터페이스
// 5개의 추상메소드 모두 재정의 해줄것!
interface MouseListener{
public void mousePressed(MouseEvent e); // 마우스 버튼을 누르는 순간 호출
public void mouseReleased(MouseEvent e); // 눌러진 마우스 버튼을 뗴는 순간 호출
public void mouseClicked(MouseEvent e); // 마우스를 클릭하는 순간
public void mouseEntered(MouseEvent e); // 마우스 컴포넌트 위에 올라가는 순간 호출
public void mouseExited(MouseEvent e); // 마우스가 컴포넌트 위에서 내려오는 순간 호출
}
리스너에 대한 오버라이딩 과정이 완료되면, 우리가 원하는 컴포넌트에 해당 리스너를 연결해줘야한다.
컴포넌트에 리스너 등록하는 과정은 아래와 같은 형태를 선언하면 된다.
형태1 : (컴포넌트).add(리스너 이름)();
형태2 : (컴포넌트).add(리스너 이름)(객체);
=> 객체 : 이 리스너 처리코드를 가지고 있는 클래스의 객체
ex1.
JButton.addActionListener();
JButton.addKeyLisener();
JButton.addFocusListener();
ex2.
JButton.addActionListener(new MyButtonLisener1());
JButton.addActionListener(new MyButtonLisener2());
JButton.addActionListener(new MyButtonLisener3());
그렇다면 인터페이스를 구현하는 이벤트 리스너를 클래스로 작성할때 어떻게 만들 수 있는지 더 자세히 알아보자.
아래와 같이 Action 이벤트(버튼을 클릭하는 액션)에 대한 처리를해줄수 있는 ActionListener 인터페이스를 재정의한다.
재정의할 메소드가 actionPerformed() 1개이다.
이때 actionPerformed() 의 인자로 들어가는 ActionEvent e 는 이벤트 객체이다.
이벤트 객체 e 는 방금 버튼을 클릭한 것에 대한 이벤트 정보를 모두 가지고 있다!
그리고 아래처럼 버튼(컴포넌트) 에 앞서 정의한 리스너인 ActionListener 를 등록해준다.
=> 버튼을 누르는 행위 (액션) 이 발생하면, 정의한 리스너의 내용이 수행된다.
전체코드
실행결과
잠깐, 복습!) 안쪽 클래스에서 "바깥클래스.this.메소드()" 형식을 호출하면 이는 바깥클래스의 메소드가 호출되는 것이였다.
형태 :
new 익명클래스의부모클래스(생성자의 인자들){
...
익명 클래스의 정의부
...
};
ex. 원래는 아래처럼 리스너 클래스를 만들고 addActionListener() 메소드로 리스너를 등록해줬었다.
// 익명 클래스 사용안하고 그냥 만든 리스너 클래스인 MyActionListener
class MyActionListener implements ActionListener{
public void actionPerformed(ActionEvent e){
...
}
}
b.addActionListner(new MyActionListener()); // 리스너 객체 등록
반면 아래와 같이 익명 클래스로 익명 객체 만들고 바로 등록가능하다.
b.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
...
}
});
리스너 객체를 익명 객체로 만들고, 그 익명객체를 addActionListener() 를 통해 해당 버튼에 바로 등록해줌
마우스를 누르는 행위에 대한 이벤트를 처리하기 위해 MouseListener 리스너 인터페이스를 구현한다.
MouseListener 인터페이스에서 mousePressed() 메소드만 재정의하고 나머지 4개 메소드는 따로 기능을 추가해서 재정의하지 않는다.
위와 같이 이벤트가 발생한 x, y좌표를 getX() 와 getY() 로 얻어온다.
그리고 "hello" 라고 문자열이 적혀있던 레이블 객체 la 를 (x,y) 좌표로 이동시키기 위해 setLocation() 속성을 활용한다!
그리고 이벤트가 발생하는 컴포넌트가 컨텐트팬(ContentPane) 이기 떄문에
( 컨텐트팬도 컴포넌트이다! 컨테이기도 하기만 컴포넌트이기도 함)
리스너 객체 컨텐트팬에 등록해준다!
=> "어댑터 클래스를 상속" 받는 것이므로, implements 가 아니라 extends 키워드를 사용하자!
ex. MouseAdapter 어댑터 클래스 정의내용
=> ActionAdapter 라는 클래스는 존재하는 존재하지 않는다.
따라서 ActionListener() 인터페이스를 구현해야함!
왼쪽은 앞서 배웠던 인터페이스 구현방법이고, 오른쪽은 지금 배우는 어댑터 클래스이다.
보듯이 어댑터는 필요한 부분만 재정의하면 된다.