7장에서 AWT 프레임워크를 활용하여 윈도우창을 열고 컴포넌트를 어떻게 배치하는지 알아봤다.
윈도우 창을 띄우고 레이블,텍스트필드,버튼 정도를 배치하는 것은 어렵지 않을 것이다. 자바는 객체지향 프로그래밍 언어이기 때문에 컴포넌트 들을 조작할 때 객체를 단위로 조작하는 것이 무엇인지 알 수 있다.
다음 단계는 이벤트를 처리하는 것이다. AWT 의 패키지를 보면 크게 두개의 패키지로 나눠진다. java.awt.* 의 awt 패키지와 java.awt.event.* 의 이벤트처리 패키지이다. awt에서 구성요소를 만들고 event에서 처리를 한다.
다음의 코드를 살펴보자. Button1 과 Butoon2 두 개의 버튼이 나온다. Button1의 이벤트는 ActionListener 인터페이스의 actionPerformed 메서드로 구현하도록 한다. 인터페이스를 구현할 때 메서드를 오버라이드하지 않으면 컴파일이 안되므로 이클립스 등 IDE에서 메서드를 구현하라고 한다. Button의 메서드 addActionListener에 인스턴스 참조를 넘겨 주면 된다. bt1.addActionListener(this) 두번째 버튼 Button2는 익명클래스를 사용했다. 경우에 따라서 이 방법이 더 나을 때도 있다. 버튼 컴포넌트가 한개 두개이거나 간단하게 작성할때 사용한다.
이벤트처리기를 구현하고 버튼을 누르면 클릭할 때마다 레이블의 텍스트가 변한다.
import java.awt.*;
import java.awt.event.*;
public class AwtGUI7 extends Frame implements ActionListener,MouseListener,MouseMotionListener{
TextField tf1;
int count=0;
Label lb1;
Label lb2;
AwtGUI7(){
tf1 = new TextField();
tf1.setBounds(50,100,200,30);
// Button 1
Button bt1 = new Button("Click to show one");
bt1.setBounds(50, 150, 150, 30);
bt1.addActionListener(this);
// Button 2
Button bt2 = new Button("Click to show another");
bt2.setBounds(50, 200, 150, 30);
bt2.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
tf1.setText("This is another one");
}
});
// Label1
lb1 = new Label("Label1");
lb1.setBounds(50,250,250,30);
// Label2
lb2 = new Label("Label2");
lb2.setBounds(50,300,250,30);
addMouseListener(this);
addMouseMotionListener(this);
add(tf1);add(bt1); add(bt2); add(lb1); add(lb2);
setTitle("Action Listener Interface");
setSize(700,700);
setLayout(null);
setVisible(true);
// Exit
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
public static void main(String[] args) {
new AwtGUI7();
}
public void actionPerformed(ActionEvent e) {
tf1.setText("Welcome to the Java Class JT " + count);
System.out.println("TextField Changed");
count++;
}
@Override
public void mouseClicked(MouseEvent e) {
lb1.setText("Mouse Clicked");
}
@Override
public void mousePressed(MouseEvent e) {
lb1.setText("Mouse Pressed (X: "+e.getX()+" Y: "+e.getY() + ")");
}
@Override
public void mouseReleased(MouseEvent e) {
lb1.setText("Mouse Released");
}
@Override
public void mouseEntered(MouseEvent e) {
lb1.setText("Mouse Entered");
}
@Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
lb1.setText("Mouse Exited");
}
@Override
public void mouseDragged(MouseEvent e) {
// TODO Auto-generated method stub
Graphics gr1 = getGraphics();
gr1.setColor(Color.BLUE);
gr1.fillRect(e.getX(), e.getY(), 10, 10);
}
@Override
public void mouseMoved(MouseEvent e) {
// TODO Auto-generated method stub
lb2.setText("X: " + e.getX() + " , Y: " + e.getY());
}
}
*마우스리스너 (MouseListener), 마우스모션리스터(MouseMotionListener)
마우스리스너는 마우스의 다섯가지 동작 Click, Pressed, Entered, Exited,Released 할 때 각각의 이벤트를 처리한다. 마찬가지로 5개의 메서드를 구현해주지 않으면 컴파일이 되지 않는다. 짐작하겠지만 마우스를 가지고 하는 몇가지 동작의 형태가 발생하면 마우스리스너가 이벤트를 발생시키는 것이다.
mouseClick : 마우스 클릭했을때 (그 자리에서)
mousePressed : 마우스를 누르고 있을때
mouseEntered : 마우스 커서가 Frame 영역에 들어올때
mouseExited : 마우스 커서가 Frame 영역에서 나갈때 (프레임에 포함된 컴포넌트에는 반응하지 않음)
mouseReleased : 마우스를 드래그 하고 놨을때
가장 기본적인 마우스 사용법에 대한 이벤트를 처리해준다. 레이블의 텍스트로 상황을 업데이트 해준다. addMouseListener(tihs)로 Frame 창에 등록한다.
*마우스 모션 리스너 (MouseMotionListener)
마우스리스너가 클릭 드래그 등의 동작을 처리했다면, 모션리스너는 드래그와 이동하는 모션을 이벤트로 취급한다.
mouseDragged : 드래그한다
mouseMoved : 이동한다
마우스를 프레임안에서 움직이면 실시간으로 X와 Y값이 바뀌는 것을 볼 수 있다. 그리고 성능은 썩 좋지 않지만 마우스 를 드래그 해서 그림을 그릴 수 있다. awt의 Graphics 클래스를 사용하면 Frame 에 그림을 그리 수 있다.
기본은 단순하다.
컴포넌트를 하나 만든다. -> 컴포넌트에 적합한 액션리스너(이벤트리스너)를 인터페이스로 구현한다. 클래스가 아니라 인터페이스로 구현하는 것은 위의 예처럼 여러개의 인터페이스를 구현할 수 있기 때문이다. 그리고 컴포넌트는 하나의 클래스로 만들 수 있는 것들 예를 들면 버튼, 체크박스 같은 분류이고, 인터페이스는 클릭하는 동작 드래그하는 동작 처럼 모든 컴포넌트에 적용 시킬 수 있는 것들이다. 컴포넌트 마다 차이가 있을 뿐이지, (텍스트필드에 입력하는 것과 리스트를 클릭하는 것은 차이가 있다) 그 클래스들에 대해 하는 행동은 유사하다.
하나의 컴포넌트에 여러개의 기능을 구현할 수도 있겠지만 우선 하나의 컴포넌트에 하나의 기능을 구현한다는 생각으로 한다면 좋을 것이다. 거대한 프로젝트도 한걸음 부터다. 천리길도 한걸음 부터, 티끌모아 태산이라는 것은 코딩에 제일 적합한 일이 아닐까 싶다. 단지 보이지 않기에 그들의 수고스러움을 모를 뿐이다.