이 문서는 hwp 형식의 문서를 한글 96으로 HTML 변환한 것입니다.
Copyright (c) 1997, Yoon Kyung Koo(yoonforh@yahoo.com), All rights reserved.

AWT 코드 업그레이드

1.0 버전의 코드를 1.1 버전으로 변환하기

awt 패키지에는 많은 변화가 있다. 자바 1.0 버전으로 작성된 코드를 1.1 버전의 컴파일러로 컴파일하더라도 실행을 할 수는 있다. 호환성을 위해 이전 버전에만 있는 도구나 클래스들을 그대로 지원하지만 API 문서를 보면 deprecated라는 태그를 이용하여 가급적 사용을 피하도록 유도하고 있다. 특히 java.awt 패키지는 기본적인 이벤트 모델의 변화를 비롯하여 수많은 변화가 있었고 새로운 모델을 따를 때에만 속도 개선과 안정성, 또 다국어 지원 등을 보장받을 수 있다.

먼저 각 도구 이름이 사소하게 변경되었다. 이것은 좀더 통일적이고 정확한 개념을 표현하기 위한 것으로 예를 들자면 java.awt.Component 클래스의 move() 도구가 setLocation()로의 변경이 이런 경우이다. 이러한 이름 변경은 단순하게 이름을 모두 변경함으로써 고칠 수 있다. 하지만 이 이름 변경은 awt 도구에서만 유효함을 명심하자. 심지어 일부 awt 도구는 변경되지 않은 경우도 있다. 결국 API 문서와 비교해보는 것이 가장 확실한 방법이다.

<그림> awt 도구 이름들 변환 표

1.0에서의 도구 이름

1.1에서 바뀐 도구 이름

addItem

add

appendText

append

inside

contains

layout

doLayout

getPageIncrement

getBlockIncrement

bounds

getBoundingBox

getBounds

getClipRect

getClipBound

locate

getComponentAt

countComponents

getComponentCount

insets

getInsets

countItems

getItemCount

location

getLocation

countMenus

getMenuCount

minimumSize

getMinimumSize

preferredSize

getPreferredSize

getCurrent

getSelectedCheckbox

size

getSize

※ sed 스크립트에서 수행하지 않습니다.

getLineIncrement

getUnitIncrement

getVisible

getVisibleAmount

insertText

insert

isSelected

isIndexSelected

allowsMultipleSelections

isMultipleMode

delItem

remove

clear

removeAll

replaceText

replaceRange

setPageIncrement

setBlockIncrement

reshape

setBounds

setEchoCharacter

setEchoChar

disable

setEnabled(false)

enable

setEnabled(true)

enable( 식 )

setEnabled( 식 )

move

setLocation

setMultipleSelections

setMultipleMode

setCurrent

setSelectedCheckbox

resize

setSize

setLineIncrement

setUnitIncrement

hide

setVisible(false)

show()

setVisible(true)

show( 식 )

setVisible( 식 )

nextFocus

transferFocus


위임형 이벤트 모델(Delegation Event Model)

도구 이름의 변화 외에도 ScrollPane(스크롤 조절을 쉽게 할 수 있는 윈도우)이나 PopupMenu(메뉴 바가 없는 메뉴)와 같은 새로운 GUI 컴퍼넌트가 추가되었다. 하지만, AWT에서 가장 큰 변화는 역시 이벤트 모델의 변화이다. 기존의 이벤트 모델은 클래스 상속에 기반한 이벤트 모델로서 부모의 이벤트 핸들러를 상속받는 것이 주된 골격이었다. 하지만 1.1 버전의 이벤트 모델은 위임형 이벤트 모델(delegation event model)이다. 서로 다른 이벤트 모델을 같은 프로그램 내에 섞어서 구현한다면 예기치 못한 결과를 야기할 수 있다.

1.1의 위임형 이벤트 모델에 기반한 프로그램 소스를 기존 1.0 버전의 handleEvent() 도구나 action() 도구에 익숙해져 있던 독자들이 보면 어리둥절할 것이다.

1.0 버전은 모든 awt 이벤트를 handleEvent() 도구에서 처리하도록 설계되었다. 그리고 각 컴퍼넌트별로 특별한 의미를 가진 이벤트는 action() 도구에서도 처리할 수 있었다. 각각의 이벤트는 주어지는 이벤트 객체의 id 값에 의해 식별되었다. 하지만 1.1 버전에서는 더 이상 동일한 Event 클래스로 주어지지 않는다. 1.1 버전의 이벤트 유형들은 java.util.EventObject를 루트 디렉토리로 하는 클래스 상속 구조에 캡슐화되어 있다. 1.1 버전의 위임형 이벤트 모델에서는 하나의 이벤트는 이벤트를 발생시키는 원천(source) 객체로부터 이벤트를 기다리는 처리(listener) 객체에로 전달된다. 즉, 원천 객체에서 이벤트가 발생되면 처리 객체의 지정된 도구를 호출한다. 이때, 발생된 이벤트 유형을 정의하는 이벤트 하위 클래스의 인스턴스가 인자로 넘겨진다.

처리 객체는 일반적인 java.util.EventListener로부터 상속된 특정한 EventListener를 구현하는 어떤 객체이다. EventListener 인터페이스는 처리할 특정한 이벤트 유형에 대응하여 이벤트 원천 객체에 의해 호출될 몇 개의 도구들을 정의한다.

원천 객체는 이벤트를 일으키거나 만들어보내는 객체이다. 원천 객체는 각 이벤트들에 해당하는 특정한 처리 객체를 등록하는 데 사용되는 set<이벤트 유형>Listener나 add<이벤트 유형>Listener 도구를 제공하여 내보낼 이벤트 집합을 정의한다.

awt 프로그램에서 전형적으로 원천 객체는 보통 GUI 구성요소이고 처리 객체는 프로그램이 이벤트의 흐름이나 처리를 제어하기 위해 적절한 Listener를 구현하는 객체이다.

이벤트는 1.0 버전에서는 java.awt.Event와 같이 하나의 Event 클래스에 의해 표현되었고 구체적인 이벤트 유형은 id 값에 의해 구별되었지만, 1.1 버전에서는 이벤트 유형이나 관계있는 이벤트 유형 그룹을 나타내는 이벤트 클래스들의 계층 구조로 이루어진다. 따라서 프로그램들은 java.util.EventObject나 다른 AWT 이벤트 클래스 중의 하나로부터 파생된 자신만의 이벤트 유형을 자유롭게 정의할 수도 있다.

<그림 17-6> 이벤트 변환 표

1.0 버전

1.1 버전

이벤트/도구

이벤트 발생 컴퍼넌트

인터페이스

인터페이스의 도구들

ACTION_EVENT/action

Button, List, MenuItem, TextField

ActionListener

actionPerformed(ActionEvent)

Checkbox, CheckboxMenuItem, Choice

ItemListener

itemStateChanged(ItemEvent)

WINDOW_DESTROY

WINDOW_EXPOSE

WINDOW_ICONIFY

WINDOW_DEICONIFY

Dialog, Frame

WindowListener

windowClosing(WindowEvent)

windowOpened(WindowEvent)

windowIconified(WindowEvent)

windowDeiconified(WindowEvent)

windowClosed(WindowEvent) (no 1.0 equivalent)

windowActivated(WindowEvent) (no 1.0 equivalent)

windowDeactivated(WindowEvent) (no 1.0 equivalent)

WINDOW_MOVED

Dialog, Frame

ComponentListener

componentMoved(ComponentEvent)

componentHidden(ComponentEvent) (no 1.0 equivalent)

componentResized(ComponentEvent) (no 1.0 equivalent)

componentShown(ComponentEvent) (no 1.0 equivalent)

SCROLL_LINE_UP

SCROLL_LINE_DOWN

SCROLL_PAGE_UP

SCROLL_PAGE_DOWN

SCROLL_ABSOLUTE

SCROLL_BEGIN

SCROLL_END

Scrollbar

AdjustmentListener

(혹은 새로 추가된 ScrollPane 클래스를 사용할 수도 있습니다.)

adjustmentValueChanged(AdjustmentEvent)

LIST_SELECT

LIST_DESELECT

Checkbox, CheckBoxMenuItem, Choice, List

ItemListener

itemStateChanged(ItemEvent)

MOUSE_DRAG/mouseDrag

MOUSE_MOVE/mouseMove

Canvas, Dialog, Frame, Panel, Window

MouseMotionListener

mouseDragged(MouseEvent)

mouseMoved(MouseEvent)

MOUSE_DOWN/mouseDown

MOUSE_UP/mouseUp

MOUSE_ENTER/mouseEnter

MOUSE_EXIT/mouseExit

Canvas, Dialog, Frame, Panel, Window

MouseListener

mousePressed(MouseEvent)

mouseReleased(MouseEvent)

mouseEntered(MouseEvent)

mouseExited(MouseEvent)

mouseClicked(MouseEvent) (no 1.0 equivalent)

KEY_PRESS/keyDown

KEY_RELEASE/keyUp

KEY_ACTION/keyDown

KEY_ACTION_RELEASE/keyUp

Component

KeyListener

keyPressed(KeyEvent)

keyReleased(KeyEvent)

keyTyped(KeyEvent) (no 1.0 equivalent)

GOT_FOCUS/gotFocus

LOST_FOCUS/lostFocus

Component

FocusListener

focusGained(FocusEvent)

focusLost(FocusEvent)

1.0에는 없는 이벤트들입니다.

ContainerListener

componentAdded(ContainerEvent)

componentRemoved(ContainerEvent)

1.0에는 없는 이벤트들입니다.

TextListener

textValueChanged(TextEvent)


코드 예제

실제로 1.0 버전으로 작성된 awt 예제 소스를 1.1 버전으로 갱신해보자.

이 프로그램은 먼저 프레임 윈도우를 생성한 후 버튼을 누르면 대화상자 윈도우를 나타내는 자바 응용 프로그램이다. 대화상자 윈도우의 텍스트 필드에 글을 입력한 후 set 버튼을 누르면 글 내용이 프레임 윈도우의 텍스트 영역에 나타난다.

먼저 sed 스크립트를 사용하여 바뀐 도구 이름들을 1.1 버전에 맞게 고친다. 이 코드에서는 resize() 도구와 TextArea 클래스의 appendText() 도구가 보인다. 각각 setSize()와 append()로 변경한다. sed 스크립트인 updateAWT를 사용하는 방법은 다음과 같다.

유닉스 환경이라면

updateAWT DialogWindow.java > temp.java

윈도우 95/NT 환경이라면

sed.exe -f updateAWT DialogWindow.java > temp.java


여기에서 생성된 temp.java가 도구 이름을 변경한 새로운 DialogWindow.java이다. 따라서 temp.java를 다른 디렉토리로 복사한 다음, 이름을 다시 DialogWindow.java로 복원하면 된다.

하지만 역시 변경이 많이 될 부분은 이벤트를 처리하는 루틴이다.

handleEvent() 도구와 action() 도구가 기존의 상속형 이벤트 모델에서 이벤트를 처리하는 대표적인 장소이다. 이 부분을 새로운 이벤트 모델로 완전히 바꾸어주어야 한다.

/* DialogWindow.java */

import java.awt.*;


public class DialogWindow extends Frame {

private boolean inAnApplet = true;

private SimpleDialog dialog;

private TextArea textArea;


public DialogWindow() {

textArea = new TextArea(5, 40);

textArea.setEditable(false);

add("Center", textArea);

Button button = new Button("Click to bring up dialog");

Panel panel = new Panel();

panel.add(button);

add("South", panel);

}


public boolean handleEvent(Event event) { // 상속형 모델의 이벤트 처리 루틴이다.

if (event.id == Event.WINDOW_DESTROY) {

if (inAnApplet) {

dispose();

} else {

System.exit(0);

}

}

return super.handleEvent(event);

}


public boolean action(Event event, Object arg) { // 상속형 모델의 이벤트 처리 루틴이다.

if (dialog == null) {

dialog = new SimpleDialog(this, "A Simple Dialog");

}

dialog.show();

return true;

}


public void setText(String text) {

textArea.appendText(text + "\n"); // 도구 이름이 1.1 버전에서 append()로 변경된다.

}


public static void main(String args[]) {

DialogWindow window = new DialogWindow();

window.inAnApplet = false;


window.setTitle("DialogWindow Application");

window.pack();

window.show();

}

}


class SimpleDialog extends Dialog {

TextField field;

DialogWindow parent;

Button setButton;


SimpleDialog(Frame dw, String title) {

super(dw, title, false);

resize(500, 200); // 도구 이름이 1.1 버전에서 setSize로 변경된다.

parent = (DialogWindow)dw;


// 대화 상자의 가운데 부분을 만든다.

Panel p1 = new Panel();

Label label = new Label("Enter random text here:");

p1.add(label);

field = new TextField(40);

p1.add(field);

add("Center", p1);


// 대화 상자의 아랫쪽 부분을 만든다.

Panel p2 = new Panel();

p2.setLayout(new FlowLayout(FlowLayout.RIGHT));

Button b = new Button("Cancel");

setButton = new Button("Set");

p2.add(b);

p2.add(setButton);

add("South", p2);


// 대화 상자의 각 구성 요소를 우선 크기로 변경하여 정렬한다.

pack();

}


public boolean action(Event event, Object arg) { // 버튼 이벤트를 처리한다.

// 상속형 모델의 이벤트 처리 루틴이다.

if ( (event.target == setButton)

| (event.target == field)) {

parent.setText(field.getText());

}

field.selectAll();

hide();

return true;

}

}


무엇보다 앞서 먼저 이벤트 클래스가 세분하여 분류되기 때문에 새롭게 분류된 이벤트 클래스들을 포함하고 있는 java.awt.event 패키지를 들여오는 것이 순서이다. 따라서 맨 앞에 다음 문장을 추가한다.

import java.awt.event.*;


또, 새로운 위임형 이벤트 모델에서는 앞에서 설명한 바와 같이 이벤트를 발생시키는 원천 객체와 이벤트를 기다리고 있는 처리 객체가 존재하므로 원천 객체에 이벤트를 처리할 처리 객체를 등록하고 또 각 이벤트 처리 루틴을 처리 객체 클래스에 구현하여야 한다.

처리 객체로 자격이 있으려면 해당 이벤트를 기다리고 있어야 한다. <이벤트 종류>Listener라는 인터페이스를 구현함으로써 그 자격을 얻을 수 있다. DialogWindow 클래스는 ActionEvent와 WindowEvent 두 가지 이벤트의 처리 객체 자격을 얻기 위해 다음과 같이 인터페이스를 구현한다.

public class DialogWindow extends Frame

implements WindowListener, ActionListener {


원천 객체에 이벤트를 등록하는 것은 add<이벤트 종류>Listener(<처리 객체>) 도구에 의해서 수행된다. DialogWindow 클래스는 내부의 버튼(원천 객체)이 발생시키는 Action 이벤트를 처리하고자 하므로 생성자에 다음 문장을 추가한다.

button.addActionListener(this);


클래스 생성자나 애플릿의 init() 도구는 이벤트가 발생하기 전에 수행되므로 이벤트 처리 객체를 등록하는 데 가장 적합한 장소이다.

마찬가지로 DialogWindow 클래스는 자신의 윈도우 종료 이벤트를 처리하기 위해 자신을 처리 객체로 지정하고 또 SimpleDialog 클래스도 텍스트 필드의 내용 변경 이벤트와 각 버튼 눌림 이벤트를 처리한다.

이제 마지막으로 handleEvent와 action에 해당하는 이벤트 처리 루틴을 구현할 차례이다. 위임형 이벤트 모델에서는 각 처리 객체가 구현한 인터페이스가 어떤 이벤트 처리 루틴을 구현해야 하는지 말해준다. 예를 들어, 윈도우 종료 이벤트를 처리하려면 WindowEvent라는 이벤트 클래스를 처리해야 하는데, 이 이벤트를 기다리는 자격을 주는 인터페이스는 WindowListener이다. WindowListener 인터페이스는 앞의 표에서와 같이 모두 일곱 개의 도구를 구현하도록 강제한다. 실제로 윈도우 종료 이벤트를 처리하는 도구는 windowClosing 도구 하나뿐이지만 나머지 여섯 개의 도구도 반드시 구현해야 한다. DialowWindow 클래스에서는 모두 도구 몸체가 없는 널 도구로 구현했다.

그리고 구체적인 이벤트 처리 내용은 내용에 따라 변경하는 방법밖에 없다.

다음은 변경을 완료한 코드 내용이다. 볼드체로 표시된 부분이 변경된 부분이다.

/* DialogWindow.java */


import java.awt.*;

import java.awt.event.*;


public class DialogWindow extends Frame

implements WindowListener,

ActionListener {

private boolean inAnApplet = true;

private SimpleDialog dialog;

private TextArea textArea;


public DialogWindow() {

textArea = new TextArea(5, 40);

textArea.setEditable(false);

add("Center", textArea);

Button button = new Button("Click to bring up dialog");

button.addActionListener(this);

Panel panel = new Panel();

panel.add(button);

add("South", panel);


addWindowListener(this);

}


public void windowClosed(WindowEvent event) {

}


public void windowDeiconified(WindowEvent event) {

}


public void windowIconified(WindowEvent event) {

}


public void windowActivated(WindowEvent event) {

}


public void windowDeactivated(WindowEvent event) {

}


public void windowOpened(WindowEvent event) {

}


public void windowClosing(WindowEvent event) {

if (inAnApplet) {

dispose();

} else {

System.exit(0);

}

}


public void actionPerformed(ActionEvent event) {

if (dialog == null) {

dialog = new SimpleDialog(this, "A Simple Dialog");

}

dialog.show();

}


public void setText(String text) {

textArea.append(text + "\n"); // 도구 이름이 변경되었다.

}


public static void main(String args[]) {

DialogWindow window = new DialogWindow();

window.inAnApplet = false;


window.setTitle("DialogWindow Application");

window.pack();

window.show();

}

}


class SimpleDialog extends Dialog implements ActionListener {

TextField field;

DialogWindow parent;

Button setButton;


SimpleDialog(Frame dw, String title) {

super(dw, title, false);

setSize(500, 200); // 도구 이름이 변경되었다.

parent = (DialogWindow)dw;


// 대화 상자의 가운데 부분을 만든다.

Panel p1 = new Panel();

Label label = new Label("Enter random text here:");

p1.add(label);

field = new TextField(40);

field.addActionListener(this);

p1.add(field);

add("Center", p1);


// 대화 상자의 아랫쪽 부분을 만든다.

Panel p2 = new Panel();

p2.setLayout(new FlowLayout(FlowLayout.RIGHT));

Button b = new Button("Cancel");

b.addActionListener(this);

setButton = new Button("Set");

setButton.addActionListener(this);

p2.add(b);

p2.add(setButton);

add("South", p2);


// 대화 상자의 각 구성 요소를 우선 크기로 변경하여 정렬한다.

pack();

}


public void actionPerformed(ActionEvent event) { // 버튼 이벤트를 처리한다.

Object source = event.getSource(); // ActionEvent를 발생시킨 객체를 찾는다.

if ( (source == setButton)

| (source == field)) {

parent.setText(field.getText());

}

field.selectAll();

hide();

}

}


First published on April 21, 1997. Last modified on April 21, 1997
자바 - 웹 프로그래밍의 진한 커피향 차례