07_ch13_pdf.hwp

Similar documents
Microsoft PowerPoint - ÀÚ¹Ù08Àå-2.ppt

Microsoft PowerPoint 자바-AWT컴포넌트(Ch8).pptx

Microsoft PowerPoint - ÀÚ¹Ù08Àå-1.ppt

<4D F736F F F696E74202D20C1A63139C0E520B9E8C4A120B0FCB8AEC0DA28B0ADC0C729205BC8A3C8AF20B8F0B5E55D>

9장.key

슬라이드 1

Cluster management software

제1장 자바 언어 소개

Cluster management software

PowerPoint Presentation

PowerPoint Template

<4D F736F F F696E74202D20C1A63233C0E520B1D7B7A1C7C820C7C1B7CEB1D7B7A1B9D628B0ADC0C729205BC8A3C8AF20B8F0B5E55D>

PowerPoint 프레젠테이션

제8장 자바 GUI 프로그래밍 II

iii. Design Tab 을 Click 하여 WindowBuilder 가자동으로생성한 GUI 프로그래밍환경을확인한다.

<4D F736F F F696E74202D20C1A63236C0E520BED6C7C3B8B428B0ADC0C729205BC8A3C8AF20B8F0B5E55D>

<4D F736F F F696E74202D20C1A63230C0E520BDBAC0AE20C4C4C6F7B3CDC6AE203128B0ADC0C729205BC8A3C8AF20B8F0B5E55D>

Microsoft PowerPoint - 06-Chapter09-Event.ppt

PowerPoint Presentation

gnu-lee-oop-kor-lec10-1-chap10

자바GUI실전프로그래밍2_장대원.PDF

(Microsoft PowerPoint - LZVNQBAJWGTC.ppt [\310\243\310\257 \270\360\265\345])

JAVA 프로그래밍실습 실습 1) 실습목표 - 메소드개념이해하기 - 매개변수이해하기 - 새메소드만들기 - Math 클래스의기존메소드이용하기 ( ) 문제 - 직사각형모양의땅이있다. 이땅의둘레, 면적과대각

Microsoft PowerPoint - 04-UDP Programming.ppt

gnu-lee-oop-kor-lec06-3-chap7

Microsoft PowerPoint - Java7.pptx

No Slide Title

PowerPoint Presentation

No Slide Title

PowerPoint Presentation

오버라이딩 (Overriding)

PowerPoint Presentation

강의자료

Java Programing Environment

Microsoft PowerPoint UI-Event.Notification(1.5h).pptx

PowerPoint Presentation

Microsoft Word - ntasFrameBuilderInstallGuide2.5.doc

11장.key

JAVA PROGRAMMING 실습 08.다형성

쉽게 풀어쓴 C 프로그래밍

<4D F736F F F696E74202D20C1A63138C0E520C0CCBAA5C6AE20C3B3B8AE28B0ADC0C729205BC8A3C8AF20B8F0B5E55D>

Microsoft PowerPoint - CSharp-10-예외처리

Microsoft PowerPoint - EEL2 Lecture10 -Swing and Event Handling.pptx

public class FlowLayoutPractice extends JFrame { public FlowLayoutPractice() { super("flowlayout Practice"); this. Container contentpane = getcontentp

PowerPoint 프레젠테이션

q 이장에서다룰내용 1 객체지향프로그래밍의이해 2 객체지향언어 : 자바 2

10장.key

C++ Programming

Cluster management software

JVM 메모리구조

Microsoft PowerPoint - 14주차 강의자료

Microsoft PowerPoint Android-SDK설치.HelloAndroid(1.0h).pptx

<4D F736F F F696E74202D20C1A63038C0E520C5ACB7A1BDBABFCD20B0B4C3BC4928B0ADC0C729205BC8A3C8AF20B8F0B5E55D>

1

PowerPoint Presentation

제이쿼리 (JQuery) 정의 자바스크립트함수를쉽게사용하기위해만든자바스크립트라이브러리. 웹페이지를즉석에서변경하는기능에특화된자바스크립트라이브러리. 사용법 $( 제이쿼리객체 ) 혹은 $( 엘리먼트 ) 참고 ) $() 이기호를제이쿼리래퍼라고한다. 즉, 제이쿼리를호출하는기호

2_안드로이드UI

쉽게 풀어쓴 C 프로그래밊

MVVM 패턴의 이해

Visual Basic 반복문

[ 그림 8-1] XML 을이용한옵션메뉴설정방법 <menu> <item 항목ID" android:title=" 항목제목 "/> </menu> public boolean oncreateoptionsmenu(menu menu) { getme

var answer = confirm(" 확인이나취소를누르세요."); // 확인창은사용자의의사를묻는데사용합니다. if(answer == true){ document.write(" 확인을눌렀습니다."); else { document.write(" 취소를눌렀습니다.");

PowerPoint 프레젠테이션

Microsoft PowerPoint - [JAVA프로그래밍]9장GUI

chap 5: Trees

Network Programming

Chap12

PowerPoint Presentation

어댑터뷰

운동시뮬레이션 강의 소개

JUNIT 실습및발표

Chapter 1

쉽게 풀어쓴 C 프로그래밍

금오공대 컴퓨터공학전공 강의자료

PowerPoint Presentation

다른 JSP 페이지호출 forward() 메서드 - 하나의 JSP 페이지실행이끝나고다른 JSP 페이지를호출할때사용한다. 예 ) <% RequestDispatcher dispatcher = request.getrequestdispatcher(" 실행할페이지.jsp");

쉽게 풀어쓴 C 프로그래밍

슬라이드 1

JAVA PROGRAMMING 실습 09. 예외처리

목차 윈도우드라이버 1. 매뉴얼안내 운영체제 (OS) 환경 윈도우드라이버준비 윈도우드라이버설치 Windows XP/Server 2003 에서설치 Serial 또는 Parallel 포트의경우.

아이콘의 정의 본 사용자 설명서에서는 다음 아이콘을 사용합니다. 참고 참고는 발생할 수 있는 상황에 대처하는 방법을 알려 주거나 다른 기능과 함께 작동하는 방법에 대한 요령을 제공합니다. 상표 Brother 로고는 Brother Industries, Ltd.의 등록 상

PowerPoint Presentation

슬라이드 1

PowerPoint 프레젠테이션

02 C h a p t e r Java

PowerPoint 프레젠테이션

Microsoft PowerPoint - Java-03.pptx

Microsoft PowerPoint - chap02-C프로그램시작하기.pptx

쉽게

ISP and CodeVisionAVR C Compiler.hwp

Cluster management software

윈도우시스템프로그래밍

09-interface.key

Microsoft PowerPoint 자바-기본문법(Ch2).pptx

2) 활동하기 활동개요 활동과정 [ 예제 10-1]main.xml 1 <LinearLayout xmlns:android=" 2 xmlns:tools="

10-Java Applet

슬라이드 1

제11장 프로세스와 쓰레드

안드로이드기본 11 차시어댑터뷰 1 학습목표 어댑터뷰가무엇인지알수있다. 리스트뷰와스피너를사용하여데이터를출력할수있다. 2 확인해볼까? 3 어댑터뷰 1) 학습하기 어댑터뷰 - 1 -

API - Notification 메크로를통하여어느특정상황이되었을때 SolidWorks 및보낸경로를통하여알림메시지를보낼수있습니다. 이번기술자료에서는메크로에서이벤트처리기를통하여진행할예정이며, 메크로에서작업을수행하는데유용할것입니다. 알림이벤트핸들러는응용프로그램구현하는데있어

Transcription:

이문서는 Java의정석 2판의 13 장입니다. 현재(2016년 3 월) 는 3 판이최신판입니다. 3판에는 AWT 가없기때문에필요하신분들을위해공개합니다. 상업적인용도가아니라면얼마든지재배포가가능합니다. - 저자남궁성 - http://cafe.naver.com/javachobostudy.cafe Chapter AWT 와애플릿 AWT & Applet

684 Java의정석定石 2판 1. AWT 자바로좀더그럴듯한프로그램을만들고싶다면 AWT 를사용하면된다. AWT는여러분 들이지금까지와는다른보다멋진자바어플리케이션을개발하도록도와줄것이다. 1.1 AWT 란? AWT(Abstract Window Toolkit) 는이름에서알수있듯이 Window 프로그래밍(GUI프로 그래밍) 을하기위한도구이다. AWT는 GUI어플리케이션의개발에필요한여러개의관 련패키지와클래스의집합으로구성되어있으며, 이들을이용하면윈도우와같은 GUI 어플리케이션을쉽고편리하게작성할수있다. GUI(Graphical User Interface) 는사용자가그래픽을통해서하드웨어와상호작용하는 환경을말한다. 지금까지는텍스트기반의어플리케이션을작성해왔지만, AWT를이용하 면그래픽기반(GUI) 의어플리케이션을작성할수있다. 텍스트기반의사용자인터페이스(Character User Interface) 는키보드로명령을내리고 결과가문자로표시되는단순한형태의것이었다. 그러나, 그래픽유저인터페이스에서는마우스등을이용하여화면의메뉴중에서하나 를선택하여작업을지시한다. GUI 는도스(DOS) 와같은텍스트기반의인터페이스와는대조적이다. GUI의요소를살 펴보면윈도(Windows), 스크롤바, 아이콘이미지, 단추들을포함한다. 1980년대후반부 터 IBM PC 및워크스테이션에서도 GUI가보급되어현재의컴퓨터는 GUI를사용하고있 다. 마이크로소프트사의윈도, 애플매킨토시의 GUI 가그예이다. AWT로작성된 GUI 어플리케이션역시플랫폼(Platform) 독립적이라서여러종류 OS에서 코드를수정하지않고도실행이가능하지만, 윈도우나버튼과같은 GUI컴포넌트들을직 접구현하지않고해당 OS 의컴포넌트(native component) 를사용하기때문에 AWT로 작성된 GUI 어플리케이션의외양(appearance) 이실행되는 OS 마다달라질수있다. 또한, 여러종류의 GUI기반의 OS들이공통적으로가지고있는컴포넌트만으로구성해야 하기때문에 AWT가제공할수있는 GUI 컴포넌트의수가제한적이다. 대신 OS 에서제공하는컴포넌트(native component) 는해당 OS에최적화되어있기때문 에자바로구현한컴포넌트보다속도가더빠르다. GUI 어플리케이션은텍스트로만구성된어플리케이션보다수행해야할작업이훨씬많기 때문에, 속도문제를안고있었던자바로써는어쩔수없이 OS독립적인부분을다소포기 하면서도속도를선택할수밖에없었던것같다. [ 참고] 여기서의플랫폼은자바(JVM) 가설치될수있는기반환경을의미한다. 플랫폼은하드웨어가될수도있고, OS 가될수도있다. 즉, OS 보다플랫폼이더넓은의미를갖는다. 예를들면, MS Windows용자바의플랫폼은 MS Windows(OS) 이고, MS Windows의플랫폼은 IBM 호환컴퓨터( 하드웨어) 이다. 그러나자바가처음소개되었던초기상황과는다르게해를거듭할수록자바의성능과하 드웨어환경이크게향상되면서자바의단점으로지적되던속도문제가점점해결되기시작 하였다. 그래서새롭게등장한것이 Swing 이다. Swing은 AWT 를확장한것이지만, AWT와는 달리순수한자바로이루어져있어서 함으로써진정한 AWT보다다양하고풍부한기능의컴포넌트를제공 GUI 어플리케이션을개발하기위한도구로사용되고있다.

Chapter 13 AWT 와애플릿(Applet) 685 Swing의클래스들이 AWT의클래스들을기반으로만들어진자손클래스들이므로 AWT 와 Swing은컴포넌트의종류와사용법만조금다를뿐나머지는거의같기때문에이책 에서는 AWT를이용한프로그래밍에대해서만살펴봐도충분하리라생각한다. 보다높은 수준의 GUI어플리케이션을개발하고자한다면 Swing을이용한어플리케이션개발에대한 책을별도로공부하는것이좋다. [ 참고] 썬에서제공하는 Swing 온라인튜터리얼(http://java.sun.com/docs/books/tutorial/uiswing/) 이상당히잘만들어져있으니 Swing으로 GUI 를개발할때꼭참고하도록하자. 그래도 Swing 이어떤것인지구경은한번해보고넘어가야할것같다. Swing으로어떤 GUI 어플리케이션을만들수있는지보려면, JDK에서제공하는데모프로그램인 SwingSet2.jar 를실행하면된다. JDK의설치경로가 C:\jdk1.5 라면, 탐색기로 C:\jdk1.5\demo\jfc\SwingSet2 디렉 토리의 SwingSet2.jar 또는 SwingSet2.html 을찾아서더블클릭하면프로그램이실행된다. 만일알집이설치되었다면, SwingSet2.jar를더블클릭했을때프로그램이실행되는대신 알집이실행될것이다. 이때는도스창을열어서아래와같은명령어를입력하면된다. C:\jdk1.5\demo\jfc\SwingSet2>java -jar SwingSet2.jar 그러면다음과같은화면이나타날것이다. [ 그림13-1] SwingSet2.jar의실행화면 이데모프로그램을살펴보면 Swing 을이어떤기능을제공하고, Swing을이용해서어떠 한일들을할수있는지충분히알수있을것이다.

686 Java의정석定石 2판 1.2 AWT 의구성 패키지명이 java.awt 로시작하는것은모두 AWT 관련패키지이다. 아래에소개한것외 에도더많은 AWT관련패키지가있지만일단지금은 java.awt와 java.awt.event패키지 만학습해도충분하다. 나머지는어떤것들이있는지살펴만보고넘어가자. java.awt 패키지명 java.awt.datatransfer java.awt.dnd java.awt.event 설명 AWT를이용한 GUI어플리케이션을작성하는데필요한기본적인클래스와컴포넌트를제공한다. 여러어플리케이션사이의, 또는단일어플리케이션내에서의데이터전송을구현하는데필요한클래스와인터페이스를제공한다. GUI 의장점중의하나인끌어놓기(Drag and Drop) 기능을구현하는데필요한클래스들을제공한다. GUI 어플리케이션에서발생하는이벤트를처리하는데필요한클래스와인터페이스를제공한다. java.awt.font 폰트와관련된클래스와인터페이스를제공한다. java.awt.image 이미지를생성하거나변경하는데사용되는클래스를제공한다. java.awt.print 출력에관련된클래스와인터페이스를제공한다. [ 표13-1] AWT와관련된패키지 메뉴와관련된컴포넌트들을제외한모든컴포넌트의조상은 Component클래스이고 Component클래스의조상은 Object 클래스이다. Component클래스와그자손클래스들은 윈도우, 스크롤바, 버튼등 GUI응용프로그램의화면을구성하는데사용되는클래스들이 다. 이들을 AWT 컴포넌트또는줄여서컴포넌트라고부른다. [ 그림13-2] AWT 컴포넌트의상속계층도

Chapter 13 AWT 와애플릿(Applet) 687 컴포넌트는버튼이나체크박스와같은일반적인컴포넌트와메뉴와관련된메뉴컴포넌트 로나누어진다. Component 는일반적인컴포넌트의최상위조상이며, MenuComponent는 메뉴관련컴포넌트들의최상위조상이다. Button Label Checkbox List Choice Scrollbar Dialog Frame TextArea와 TextField FileDialog [ 그림13-3] AWT가제공하는컴포넌트

688 Java의정석定石 2판 MenuComponent MenuBar MenuItem Menu PopupMenu CheckboxMenuItem [ 그림13-4] AWT 메뉴컴포넌트의상속계층도 MenuItem MenuBar Menu ChechboxMenuitem Separator [ 그림13-5] GUI 어플리케이션의메뉴구성에사용되는 AWT컴포넌트 1.3 컴포넌트(Component) Component는 MenuComponent를제외한 AWT의모든컴포넌트의조상이고추상클래 스이다. Component에는컴포넌트들이가져야할공통적인메서드들을정의해놓고있으 며, 주로사용되는메서드는다음과같다. [ 참고] 이외에도많은메서드들이있으며, 보다자세한것은 Java API 문서를참고하자. 메서드 Color getbackground() void setbackground(color c) Cursor getcursor() void setcursor(cursor c) Font getfont() void setfont(font f) Color getforeground() void setforeground(color c) int getheigtht() int getwidth() void setbounds(int x, int y, int width, int height) Rectangle getbounds() 컴포넌트의배경색을얻는다. 설명 컴포넌트의배경색을지정된색으로변경한다. 컴포넌트에지정된커서를얻는다. 컴포넌트의커서( 마우스포인터) 를지정한다. 컴포넌트에지정되어있는 컴포넌트의 Font 를지정한다. 컴포넌트의전경색을얻는다. 컴포넌트의전경색을지정한다. Font 를얻는다. 컴포넌트의높이(Height) 를얻는다. 컴포넌트의폭(Width) 를얻는다. 컴포넌트의위치(x, y) 와크기(width, height) 를지정한다. 컴포넌트의위치와크기(Rectangle 객체) 를얻는다.

Chapter 13 AWT 와애플릿(Applet) 689 Point getlocation() void setlocation(int x, int y) Dimension getsize() void setsize(int width, int height) boolean hasfocus() void requestfocus() void paint(graphics g) void repaint() 컴포넌트의위치를얻는다. 컴포넌트의위치를지정한다. 컴포넌트의크기를얻는다. 컴포넌트의크기를지정한다. 컴포넌트가현재 컴포넌트가 focus 를갖고있는지알려준다. focus 를갖도록한다. 컴포넌트를화면에그린다. 컴포넌트를화면에다시그린다. void setenabled(boolean b) 컴포넌트를사용가능(true)/ 불가능(false) 하게한다. Container getparent() 컴포넌트가포함되어져있는컨테이너(parent) 를얻는다. void setvisible(boolean b) 컴포넌트가화면에보이게(true)/ 보이지않게(false) 한다. [ 표13-2] Component클래스의메서드 1.4 컨테이너(Container) Component의자손들중에 Container와그자손들이있는데, 이들을컨테이너라고부른 다. 컨테이너는다른컴포넌트들을포함할수있어서 Button, Label과같은컴포넌트들을 포함할수있다. 또한컨테이너가컨테이너를포함할수도있다. 1. 독립적인컨테이너 - 독립적으로사용될수있으며, 다른컴포넌트나종속적인컨테이너를포함 할수있다. 컨테이너 Frame Window Dialog 설명 가장일반적인컨테이너로윈도우와모양이같다. titlebar 와크기조절버튼, 닫 기버튼을가지고있다. 그리고메뉴를추가할수있다. Frame 의조상이며, 경계선, titlebar, 크기조절버튼, 닫기버튼이없으며, 메뉴 도추가할수없다. 단지컴포넌트를담을수있는평면공간만을갖는다. Frame 처럼, titlebar 와닫기버튼을갖고있지만, 메뉴는가질수없으며기본 적으로크기를변경할수없다. 주로프로그램사용자에게메시지를보여주거 나, 응답을받는데사용한다. 2. 종속적인컨테이너 - 독립적으로사용될수없으며, 다른컨테이너에포함되어야만한다. Panel 컨테이너 ScrollPane 평면공간으로 될수는없다. 설명 Frame과같이여러컴포넌트를담을수있으나단독적으로사용 Panel 과같은평면공간이지만, Panel과는달리단하나의컴포넌트만포함할 수있으며자신보다큰컴포넌트가포함되면스크롤바가자동적으로나타난다. 컨테이너에는여러개의오버로딩(overloading) 된 add 메서드들이정의되어있어서, 컨테 이너에단순히 add 메서드를사용하는것만으로다른컴포넌트들을포함시킬수있다. 컨 테이너에포함된컴포넌트들은기본적으로컨테이너에설정된배경색 (background color) 과전경색(foreground color), 글자체등의설정을그대로따르게된다.

690 Java의정석定石 2판 메서드 설명 Component[] getcomponents() 컨테이너에포함되어있는모든컴포넌트를얻는다. Component getcomponent(int n) 컨테이너에 n 번째로추가된컴포넌트를얻는다. Component getcomponentat(int x, int y) 컨테이너의지정된위치(x, y) 에있는컴포넌트를얻는다. Component add(component comp) 컨테이너에컴포넌트를추가한다. void remove(component comp) 컨테이너에서지정된컴포넌트를제거한다. Insets getinsets() LayoutManager getlayout() 컨테이너의경계의크기를알수있는얻는다. 컨테이너에설정되어있는다. Inset객체를 LayoutManager를얻는 void setlayout(layoutmanager mgr) 컨테이너에 LayoutManager 를설정한다. [ 표13-3] Container의메서드 2. AWT 의주요컴포넌트 이제 AWT를이용한 GUI프로그래밍에사용되는컴포넌트들의종류와기본적인기능에 대해서자세히알아보자. 2.1 Frame GUI 프로그래밍의가장대표적인컴포넌트로다른컴포넌트들을포함할수있는컨테이너 이다. titlebar 와최대화버튼, 최소화버튼, 닫기버튼이있으며크기를조절할수있다. 메서드또는생성자 Frame(String title) String gettitle() void settitle(string title) void setstate(int state) int getstate() void setresizable(boolean resizable) 설명 Frame 을생성한다. title - Frame의 titlebar에보여질 text titlebar에있는 text 를얻는다. titlebar의 text 를변경한다. Frame 의상태를변경할수있으며, state에는아래의두가지값중하나를사용할수있다. Frame.ICONIFIED - Frame 을최소화상태가되게한다. Frame.NORMAL - Frame 을정상적인상태( 최소화이전상태) 가되게한다. Frame 의현재상태를알수있다. Frame 의크기를변경가능또는불가능하게한다. (resizable의값이 false로하면사용자가 Frame의크기를 변경할수없다.) [ 표13-4] Frame의메서드

Chapter 13 AWT 와애플릿(Applet) 691 [ 예제13-1]/ch13/FrameTest.java import java.awt.*; class FrameTest { public static void main(string args[]) { Frame f = new Frame("Login"); // Frame 객체를생성한다. f.setsize(300, 200); // Frame 의크기를설정한다. f.setvisible(true); // 생성한 Frame 을화면에보이도록한다. [ 실행결과] 이예제는단순히 Frame 하나를화면에보여주는것인데, 실행결과그림은윈도우즈에서 실행한것이기때문에윈도우즈의윈도우와똑같은모습을하고있다.( 맥OS에서위의예 제를실행했다면, 맥OS의윈도우와같은모양의 Frame이화면에나타났을것이다.) [ 참고] AWT는 OS의컴포넌트들을그대로사용하는것이기때문에 AWT응용프로그램의외향은실행되는 OS에따라달라지게된다. 크기조절도되고, titlebar 를드래그하면이동할수도있는등, 윈도우즈의윈도우와같은 기능을가지고있다. 단, 닫기버튼은눌러도아무작동을하지않는데이것을가능하게하 려면나중에배울이벤트처리를이용해서기능을추가해주어야한다. 이예제의실행을멈추려면, 콘솔( 도스창) 에서 Ctrl 키+c 를누르던가, 윈도우즈에서 Ctrl+Alt+Delete키를누른후 java.exe 를선택하도록한다. 1. Frame 객체를하나만들고, - 생성자에사용된 String은 Frame의 titlebar 에나타난다. Frame f = new Frame("Login"); 2. 생성된 Frame 의크기를설정한다음, - 폭(width) : 300 픽셀(pixel), 높이 : 200 픽셀 f.setsize(300, 200); 3. Frame 을화면에보이도록한다. - Frame객체를생성했다고해서화면에보이는것은아니고 반드시 setvisible() 을사용해야화면에나타난다. f.setvisible(true); Frame 객체의설정작업( 크기조절) 이모두끝난후에마지막으로 setvisible() 을호출하도 록한다. 만일 setsize() 보다 setvisible(true) 를먼저호출하면, Frame의크기가변경되는과정 이, 아주짧은시간동안이지만, 화면에보일것이다. 이렇게되면, 보기에도좋지않을뿐 더러 Frame 이변경될때마다화면을갱신해야하므로비효율적이다. [ 참고] setsize() 와 setvisible() 은 Frame의조상인 Component 에정의된메서드이다.

692 Java의정석定石 2판 [ 참고] Editplus에서 AWT프로그래밍을할때는옵션을아래의그림과같이 java.exe의 Capture Output옵션을해제하는것이좋다. Frame 에이벤트처리를하지않았기때문에예제의실행을멈추기가어렵기때문이다. [ 그림13-6] Editplus에서 java.exe의 Capture output옵션을해제하는방법 예제13-1을실행시키면, Frame이모니터화면의좌측상단에나타나는데다음예제는 Toolkit클래스의 getscreensize() 를이용해서 Frame 이화면의중앙에나타나게한다. [ 예제13-2]/ch13/FrameTest2.java import java.awt.*; class FrameTest2 { public static void main(string args[]) { Frame f = new Frame("Login"); f.setsize(300, 200); Toolkit tk = Toolkit.getDefaultToolkit(); // 구현된 Toolkit 객체를얻는다. Dimension screensize = tk.getscreensize(); // 화면의크기를구한다. // 화면크기의절반값에서 Frame크기의절반값을뺀위치로하면 // Frame 이화면가운데위치하게된다. f.setlocation(screensize.width/2-150, screensize.height/2-100); f.setvisible(true); // 생성한 Frame 을화면에보이도록한다.

Chapter 13 AWT 와애플릿(Applet) 693 [ 실행결과] screensize.width (b) (a) screensize.height (a) screensize.width / 2 - Frame 너비 / 2 (b) screensize.height / 2 - Frame 높이 / 2 2.2 Button Button 은사용자가클릭했을때, 어떤작업이수행되도록할때사용된다. Button(String label) 메서드또는생성자 String getlabel() void setlabel(string label) 설명지정된 label을가진 Button 을생성한다. label - Button위에나타날 text Button에나타나있는 text 를얻는다. Button에나타나있는 text 를변경한다. [ 예제13-3]/ch13/ButtonTest.java import java.awt.*; [ 표13-5] Button의메서드 class ButtonTest { public static void main(string args[]) { Frame f = new Frame("Login"); f.setsize(300, 200); Button b = new Button(" 확인"); // Button 위에 " 확인" 이라는글자가나타난다. b.setsize(100, 50); // Button 의크기를설정한다. f.add(b); // 생성된 Button을 Frame 에포함시킨다. f.setvisible(true);

694 Java의정석定石 2판 [ 실행결과] Frame 은컨테이너이므로다른컴포넌트들을포함할수있다. 이예제에서는 Button을하 나생성한후 add메서드를이용해서 Frame 에포함시켰다. 이와같은방식으로 Frame에 여러가지다양한컴포넌트들을추가함으로써여러분들이그동안보아왔던것과같은윈 도우를만들수있을것이다. 위의예제를실행한후, 나타난화면을보고여러분들이예상했던화면과좀다르다고 생각했을것이다. Button의크기를폭 100 픽셀, 높이 50 픽셀로설정했는데, 크기가 300 픽셀, 200픽셀크기 의 Frame 에가득차있다. 그리고 Frame의모서리를드래그하여 Frame의크기를변경 시키면, Button 의크기도같이변경되는것을볼수있을것이다. 그이유는바로 Frame 에설정되어있는레이아웃매니저(Layout Manager) 때문이다. 컨 테이너에는레이아웃매니저를선택적으로설정할수있는데, 레이아웃매니저는컨테이 너의크기가변경될때마다컨테이너에포함된컴포넌트들의크기와위치를자동적으로 관리해준다. 따라서프로그래머가수동적으로일일이컨테이너내의컴포넌트배치에대해신경쓰지 않아도되는장점이있다. 기존의 Visual Basic과같은기존의 GUI프로그래밍에는레이 아웃매니저개념이없어서, 윈도우의크기가변경될때윈도우내의컴포넌트들을재배치 해주는코드를프로그래머가별도로작성해야만한다. [ 참고] Frame에는기본적으로레이아웃매니저가 BorderLayout 으로설정되어있으며, 레이아웃매니저의종류와특성등자세한내용은앞으로배우게될것이다. 아래의예제는위의예제에서기본적으로설정된레이아웃매니저를없애고, Button의크기와위치를수동적으로설정해준것이다. [ 예제13-4]/ch13/ButtonTest2.java import java.awt.*; class ButtonTest2 { public static void main(string args[]) { Frame f = new Frame("Login"); f.setsize(300, 200); f.setlayout(null); // 레이아웃매니저의설정을해제한다.

Chapter 13 AWT 와애플릿(Applet) 695 Button b = new Button(" 확인"); b.setsize(100, 50); // Button 의크기를설정한다. b.setlocation(100, 75); // Frame내에서의 Button 의위치를설정한다. f.add(b); f.setvisible(true); [ 실행결과] 컨테이너의레이아웃을설정해주는 setlayout() 에 null 값을넣어줌으로써, Frame에아무 런레이아웃매니저도지정되어있지않도록한다. 그렇기때문에, 이제는 Frame의크기 를변경해도 Button 의크기와위치에는전혀변화가없다. 대신 Button 의크기와위치를수동적으로직접지정해주어야한다. 그래서 setlocation () 과 setsize() 를통해 Button 의크기와위치를지정해주었다. 이예제에사용된 setlocation() 역시 Component클래스에정의된메서드로서모든컴 포넌트에사용할수있는메서드이다. 지금이예제에서는 Button이눌러졌을때수행해야할코드를적어주지않았으므로 Button 을눌러도아무런일도일어나지않는다. Button이눌러졌을때어떤작업을하도 록하기위해서는 Button 에이벤트처리를해주어야하는데, 이벤트처리에대해서는나중 에자세히배우게될것이다.

696 Java의정석定石 2판 2.3 Choice 여러개의 item 이있는목록을보여주고, 그중에서한가지를선택하도록할때 Choice 를사용한다. [ 참고] 기존의 GUI 프로그래밍에서는 Choice 를콤보박스(combo box) 또는드랍다운리스트박스(drop-down listbox) 라고부른다. 메서드또는생성자 void add(string item) Choice에 item 을추가한다. void remove(string item) Choice에서 item 을제거한다. [ 표13-6] Choice의메서드 [ 참고] index는 0 부터시작하므로, 첫번째 item의 index값은 0 이다. 설명 void remove(int index) 지정된순서에있는 item 을제거한다. void removeall() Choice의모든 item 을제거한다. void insert(string item, int index) 지정된순서에 item 을추가한다. String getitem(int index) 지정된순서의 item 을얻는다. int getitemcount() 현재 Choice에추가되어있는 item 이몇개인지알려준다. int getselectedindex() 현재선택되어져있는 item의 index 값을얻는다. String getselecteditem() 현재선택되어져있는 item 을얻는다. [ 예제13-5]/ch13/ChoiceTest.java import java.awt.*; class ChoiceTest { public static void main(string args[]) { Frame f = new Frame("Choice - Select"); f.setsize(300, 200); f.setlayout(null); Choice day = new Choice(); day.add("sun"); day.add("mon"); day.add("tue"); day.add("wed"); day.add("thu"); day.add("fri"); day.add("sat"); // Choice객체를생성한다음 // Choice 의목록에나타날값들을추가한다. day.setsize(100, 50); day.setlocation(100, 70); f.add(day); f.setvisible(true);

Chapter 13 AWT 와애플릿(Applet) 697 [ 실행결과] add() 를이용하면 Choice에나타날항목을추가할수있으며, 화살표버튼을누르면추가한항목들이순서대로나타난다.

698 Java의정석定石 2판 2.4 List List 역시 Choice 처럼목록에서중에서원하는항목(item) 을선택할수있도록할때사 용된다. 그러나 List는 Choice 와는달리, 처음부터모든 item 목록을보여주며, 목록의 item 중에서하나또는여러개를선택하도록할수있다. 메서드또는생성자 List(int rows, boolean multiplemode) List(int rows) List() void add(string item) item을 List 에추가한다. 설명 rows - 몇줄짜리크기의 List 를보여줄것인지지정한다. multiplemode - List목록다중선택이가능하도록할것인가를지정할수있다. true로하면여러개의 item을선택할수있다. List에보여줄 item 수만지정한다. multiplemode의값은 false 로지정되어하나의목록만선택가능하다. rows의값은기본값인 4 로지정되고, multiplemode의값은 false가되어하나의 item 만선택가능하다. void add(string item, int index) 지정된위치(index) 에 item 을추가한다. void replaceitem(string newvalue, int index) void remove(string item) void remove(int index) void removeall() 지정된위치(index) 의 item을새로운 item(newvalue) 로 바꾼다. List에서해당 item 을제거한다. index - 지정된위치에있는 item 을제거한다. List의모든 item 을제거한다. int getrows() List에 scroll없이볼수있는 item 의수를얻는다. String getitem(int index) index - 지정된위치에있는 item 을얻는다. String[] getitems() List에있는모든 item 을얻는다. int getitemcount() void select(int index) void deselect(int index) List에있는 item 이모두몇개인지알려준다. (getrows() 와비교해볼것) 지정된위치에있는 지정된위치에있는 item 을선택한다. item 을선택해제한다. int getselectedindex() 현재선택되어있는 item의 index 값을얻는다. int[] getselectedindexes() 현재선택되어있는 item들의 index 값을얻는다. (List의 multiplemode가 true 인경우) String getselecteditem() 현재선택되어있는 item 을얻는다. String[] getselecteditems() 현재선택되어있는 item 들을얻는다. (multiplemode가 true 인경우) boolean isindexselected(int index) 지정된위치의 item 이선택되어있는지알려준다. void setmultiplemode(boolean b) List를 multiplemode 로할것인지결정한다. b - true 면, List를 multiplemode 로설정한다. [ 표13-7] Choice의메서드 [ 예제13-6]/ch13/ListTest.java import java.awt.*; class ListTest { public static void main(string args[]) {

Chapter 13 AWT 와애플릿(Applet) 699 Frame f = new Frame("List - Select"); f.setsize(300, 200); f.setlayout(null); List selectone = new List(6); // 6개목록을보여줄수있는크기의 List 를만든다. selectone.setlocation(20,40); selectone.setsize(100, 120); selectone.add("student"); selectone.add("teacher"); selectone.add("driver"); selectone.add("computer Programmer"); selectone.add("sales Man"); selectone.add("musician"); selectone.add("director"); // 생성자의두번째인자값을 true로설정해서 List 의목록에서여러개를선택할수있게했다. List selectmany = new List(6, true); selectmany.setlocation(150, 40); selectmany.setsize(100,120); selectmany.add("student"); selectmany.add("teacher"); selectmany.add("driver"); selectmany.add("computer Programmer"); selectmany.add("sales Man"); selectmany.add("musician"); selectmany.add("director"); f.add(selectone); f.add(selectmany); f.setvisible(true); [ 실행결과]

700 Java의정석定石 2판 2.5 Label Label 를사용하면화면에글자를표시할수있으며, 데주로사용된다. 설명이나메시지를화면에나타내는 메서드또는생성자설명 Label(String text, int alignment) Label(String text) text - 화면에나타낼글(text) 을 String 으로넣는다. alignment -text 의정렬방식을지정한다. Label.LEFT, Label.CENTER, Label.RIGHT 중하나를사용. text - 화면에나타낼 text 를지정한다. alignment의기본값인 Label.LEFT 로설정된다. String gettext() Label의 text 를얻어온다. void settext(string text) Label의 text 를주어진값으로변경한다. void setalignment(int alignment) Label의 text 정렬을지정한다. Label.LEFT, Label.CENTER, Label.RIGHT 중하나를사용. [ 예제13-7]/ch13/LabelTest.java import java.awt.*; [ 표13-8] Label의주요메서드 class LabelTest { public static void main(string args[]) { Frame f = new Frame("Login"); f.setsize(300, 200); f.setlayout(null); Label id = new Label("ID :"); // Label 을생성하고크기와위치를지정한다. id.setbounds(50, 50, 30, 10); // 50, 50위치에크기가가로 30, 세로 10 Label pwd = new Label("Password :"); pwd.setbounds(50, 65, 100, 10); f.add(id); // 생성한 Label을 Frame 에포함시킨다. f.add(pwd); f.setvisible(true); [ 실행결과] [ 참고] Frame에 Layout Manager 가설정되지않았을때, setsize() 또는 setbounds() 를이용해서컴포넌트들의크기를지정해주지않으면컴포넌트가화면에나타나지않는다.

Chapter 13 AWT 와애플릿(Applet) 701 2.6 Checkbox Checkbox는 boolean과같이 true/false 또는 on/off와같이둘중의한값을가질수있 는컴포넌트다. 또 CheckboxGroup 을이용하면, 여러가지값들중에서한가지를선택 할수있는 radio button 도만들수있다. 메서드또는생성자 Checkbox(String text, boolean state) Checkbox(String text) Checkbox() Checkbox(String text, CheckboxGroup group, boolean state) 설명 text - Checkbox와함께보여질 text 를지정한다. state - true이면 Checkbox 가선택된상태로생성되고, false이면 Checkbox 가선택해제된상태로생성된다. Checkbox와함께보여질 text 를지정한다. Checkbox는선택해제된상태로생성된다. text없이 Checkbox 만나타나고, Checkbox는선택해제된상태로생성된다. group - CheckboxGroup 객체의참조. CheckboxGroup을이용해서 radio button 으로만든다. String getlabel() Checkbox의 label 을얻는다. void setlabel(string label) Checkbox의 label 을주어진값으로변경한다. boolean getstate() void setstate(boolean state) Checkbox 의상태를얻는다. 결과값이 true면체크되어있는상태이다. Checkbox 의상태를설정한다. state값을 true로하면 Checkbox 가체크되어있는상태가되도록한다. [ 표13-9] CheckBox의메서드 [ 예제13-8]/ch13/CheckboxTest.java import java.awt.*; class CheckboxTest { public static void main(string args[]) { Frame f = new Frame("Questions"); f.setsize(305, 250); // Frame의 LayoutManager를 FlowLayout 으로설정한다. f.setlayout(new FlowLayout()); Label q1 = new Label("1. 당신의관심분야는?( 여러개선택가능)"); Checkbox news = new Checkbox("news", true); // 선택된상태로생성 Checkbox sports = new Checkbox("sports"); Checkbox movies = new Checkbox("movies"); Checkbox music = new Checkbox("music"); f.add(q1); f.add(news); f.add(sports); f.add(movies); f.add(music); Label q2 = new Label("2. 얼마나자주극장에가십니까?"); CheckboxGroup group1 = new CheckboxGroup(); Checkbox movie1 = new Checkbox(" 한달에한번갑니다.", group1, true); Checkbox movie2 = new Checkbox(" 일주일에한번갑니다.", group1, false); Checkbox movie3 = new Checkbox(" 일주일에두번갑니다.", group1, false); f.add(q2); f.add(movie1); f.add(movie2); f.add(movie3);

702 Java의정석定石 2판 Label q3 = new Label("3. 하루에얼마나컴퓨터를사용하십니까?"); CheckboxGroup group2 = new CheckboxGroup(); Checkbox com1 = new Checkbox("5 시간이하 ", group2, true); Checkbox com2 = new Checkbox("10 시간이하", group2, false); Checkbox com3 = new Checkbox("15 시간이상", group2, false); f.add(q3); f.add(com1); f.add(com2); f.add(com3); f.setvisible(true); [ 실행결과] 위의예제는 Checkbox와 Label 을이용해서몇가지질문을만든것이다. Frame의레이 아웃매니저를 따로설정하지않았다. 첫번째질문의 FlowLayout으로설정하였기때문에사용된컴포넌트들의크기와위치는 Checkbox들은그룹화하지않았기때문에각각독립적으로선택가능하 다. 4 가지모두를선택할수도있고, 4 가지모두선택하지않을수도있다. 실행했을때, news가선택되어진이유는생성자의두번째매개변수에 true를설정했기 때문이다. 기본적으로는 false기때문에이처럼따로값을지정하지않으면선택되지않은 상태로나타난다. Checkbox news = new Checkbox("news", true); // 선택된상태로생성 두번째와세번째질문은 Checkbox들을 CheckboxGroup(group1과 group2) 을이용해 서그룹화하였기때문에라디오버튼(radio button) 이되었다. 이그룹화된 Checkbox들 은, 같은그룹내의 Checkbox 들중에서한가지만선택할수있다.

Chapter 13 AWT 와애플릿(Applet) 703 2.7 TextField 사용자로부터값을입력을받을수있는컴포넌트이다. 편집이가능하며한줄만입력할수있어서이름, id, 비밀번호등비교적짧은값의입력에사용된다. 메서드또는생성자 TextField(String text, int col) TextField(int col) 설명 text - TextField에보여질 text 를지정한다. col - 입력받을글자의수를적는다. col의값에따라서 TextField 의크기가결정된다. col - 입력받을글자의수를적는다. TextField(String text) text - TextField에보여질 text 를지정한다. void setechochar(char c) int getcolumns() 지정된문자를 EchoChar 로한다. ( 비밀번호입력에주로사용됨) TextField 의칼럼수를얻는다. void settext(string t) * 지정된문자열을 TextField의 text 로한다. String gettext() * TextField의 text 를얻는다. void select(int selectionstart, int selectionstart부터 selectionend까지의 text 를선택( 하이라이 selectionend) * 트) 한다. void selectall() * TextField의모든 text 를선택된상태가되도록한다. String getselectedtext() * TextField의 text 중선택되어진부분을얻는다. void seteditable(boolean b) * TextField의 text 를편집가능(true)/ 불가능(false) 하도록한다. [ 표13-10] TextField의메서드 [ 참고] '*' 표시가되어있는것은 TextField의조상인 TextComponent 로부터상속받은것이다. [ 예제13-9]/ch13/TextFieldTest.java import java.awt.*; class TextFieldTest { public static void main(string args[]) { Frame f = new Frame("Login"); f.setsize(400, 65); f.setlayout(new FlowLayout()); // LayoutManager를 FlowLayout 으로 한다. Label lid = new Label("ID :", Label.RIGHT); // 정렬을오른쪽으로. Label lpwd = new Label("Password :", Label.RIGHT); TextField id = new TextField(10);// 약 10개의글자를입력할수있는 TextField 생성 TextField pwd = new TextField(10); pwd.setechochar('*'); // 입력한값대신 '*' 가보이도록한다. f.add(lid); // 생성한컴포넌트들을 Frame 에포함시킨다. f.add(id); f.add(lpwd); f.add(pwd); f.setvisible(true);

704 Java의정석定石 2판 [ 실행결과] TextField 는예제를실행시켜보는것만으로도다른설명이필요없을정도로여러분들에 게익숙한컴포넌트일것이다. 패스워드를입력하는 TextField에는 void setechochar(char c) 를사용하면, 입력하는 값에관계없이화면에는지정된문자 '*' 가보이게된다. 그렇다할지라도, TextField는 실제로입력한값을갖게된다. 여기서도 Frame의레이아웃매니저를 FlowLayout 으로하였기때문에, Frame내의컴포 넌트들의크기와위치를따로지정하지않았다. [ 참고] TextField 에는이외에도많은기능들이있는데, AWT 의이벤트처리에서더자세히배우게될것이다. 2.8 TextArea TextArea는여러줄의 text 를입력하거나보여줄수있는편집가능한컴포넌트이다. 그 리고스크롤바를이용해서실제화면에보이는것보다많은양의 메서드또는생성자 TextArea(String text, int row, int col, int scrollbar) TextArea(int row, int col) 설명 text 를담을수있다. text - TextArea에보여질 text 를지정한다. row - TextArea 의줄(row) 수를지정한다. col - TextArea 의열(column) 수를적는다. scrollbar - TextArea에사용할 scrollbar의종류와사용여부지정. 아래의 4가지값중에서하나를선택 TextArea.SCROLLBARS_BOTH TextArea.SCROLLBARS_NONE TextArea.SCROLLBARS_HORIZONTAL_ONLY TextArea.SCROLLBARS_VERTICAL_ONLY row - TextArea 의줄(row) 수를지정한다. col - TextArea 의열(column) 수를적는다. 아무런 text도없는빈 TextArea 를생성한다. scrollbar는수평(horizontal), 수직(VERTICAL) 모두갖는다. int getrows() TextArea 의행(row) 의개수를얻는다. int getcolumns() TextArea 의열(column) 의개수를얻는다. void setrows(int rows) 지정된값으로 TextArea 의행(row) 의개수를설정한다. void setcolumns(int columns) 지정된값으로 TextArea 의열(column) 의개수를설정한다. void append(string str) TextArea에있는 text 의맨마지막에문자열을덧붙인다. void insert(string str, int pos) TextArea에있는 text 의지정된위치에문자열을넣는다. void replacerange(string str, int start, int end) TextArea에있는 text의 start부터 end범위에있는문자열을 str 에지정된값으로변경한다. void settext(string t) * 지정된문자열을 TextArea의 text 로한다. String gettext() * TextArea의 text 를얻는다.

Chapter 13 AWT 와애플릿(Applet) 705 void select(int selectionstart, int selectionstart부터 selectionend까지의 text가선택되게한 selectionend) * 다. void selectall() * TextArea의모든 text 를선택되게한다. String getselectedtext() * TextArea의 text 중선택된부분을얻는다. void seteditable(boolean b) * TextArea의 text 를편집가능(true)/ 불가능(false) 하도록한다. [ 표13-11] TextArea의메서드 [ 참고] '*' 표시가되어있는것은 TextArea의조상인 TextComponent로부터상속받은것이다. [ 예제13-10]/ch13/TextAreaTest.java import java.awt.*; class TextAreaTest { public static void main(string args[]) { Frame f = new Frame("Comments"); f.setsize(400, 220); f.setlayout(new FlowLayout()); TextArea comments = new TextArea(" 하고싶은말을적으세요.", 10, 50); f.add(comments); comments.selectall(); // TextArea의 text 전체가선택되도록한다. f.setvisible(true); [ 실행결과]

706 Java의정석定石 2판 2.9 Scrollbar Scrollbar는사용자가정해진범위내에있는값을쉽게선택할수있도록해주는컴포넌 트이다. 주로볼륨설정이나, 속도조절, 색상선택과같은곳에사용된다. 메서드또는생성자 Scrollbar() Scrollbar(int orientation) Scrollbar(int orientation, int value, int visible, int min, int max) 설명 orientation - Scrollbar 의종류를지정해준다. Scrollbar.VERTICAL, Scrollbar.HORIZONTAL 중의하나 value - Scrollbar의초기값 visible - Scroll 버튼(bubble) 의크기 min - Scrollbar가가질수있는최소값 max - Scrollbar가가질수있는최대값 int getvalue() 현재설정된 Scrollbar 의값을얻어온다. void setvalue(int newvalue) Scrollbar 의값을지정된값(newValue) 으로설정한다. [ 표13-12] Scrollbar의메서드 [ 예제13-11]/ch13/ScrollbarTest.java import java.awt.*; class ScrollbarTest { public static void main(string args[]) { Frame f = new Frame("Scrollbar"); f.setsize(300, 200); f.setlayout(null); Scrollbar hor = new Scrollbar(Scrollbar.HORIZONTAL, 0, 50, 0, 100); hor.setsize(100, 15); hor.setlocation(60, 30); Scrollbar ver = new Scrollbar(Scrollbar.VERTICAL, 50, 20, 0, 100); ver.setsize(15, 100); ver.setlocation(30, 30); f.add(hor); f.add(ver); f.setvisible(true); [ 실행결과]

Chapter 13 AWT 와애플릿(Applet) 707 2.10 Canvas Canvas는이름에서알수있듯이빈평면공간을제공하는컴포넌트이다. 여기에그림을 그릴수도있고, 글자를적을수도있다. 주로그림을그리거나이미지를위한공간으로사 용되며, 사용자정의컴포넌트를만들때도사용된다. [ 예제13-12]/ch13/CanvasTest.java import java.awt.*; class CanvasTest { public static void main(string args[]) { Frame f = new Frame("CanvasTest"); f.setsize(300, 200); f.setlayout(null); // Frame의 Layout Manager 설정을해제한다. Canvas c = new Canvas(); c.setbackground(color.pink); // Canvas 의배경을분홍색(pink) 으로한다. c.setbounds(50, 50, 150, 100); f.add(c); // Canvas을 Frame 에포함시킨다. f.setvisible(true); [ 실행결과]

708 Java의정석定石 2판 2.11 Panel Panel은 Frame 과같이다른컴포넌트를자신의영역내에포함시킬수있는컨테이너다. 동시에 Panel 자신이다른컨테이너에포함될수있기도하다. 심지어는 Panel이 Panel 에포함되는것도가능하다. Panel은 Frame과는달리 titlebar 나버튼도없고, 단지비어있는평면공간만을갖는다. Panel 도컨테이너라자신만의레이아웃(Layout) 을유지할수있어서, Panel을이용하면 Frame 내에서컴포넌트들의배치를다양하게할수있다. 앞으로레이아웃관리자에대해 서배우게될텐데, 이때 Panel이컴포넌트의배치에얼마나유용하게사용될수있는지 알수있을것이다. [ 예제13-13]/ch13/PanelTest.java import java.awt.*; class PanelTest { public static void main(string args[]) { Frame f = new Frame("Panel"); f.setsize(300, 200); f.setlayout(null); // Frame이 Layout Manager 를사용하지않도록한다. Panel p = new Panel(); p.setbackground(color.green); p.setsize(100, 100); p.setlocation(50, 50); // Panel 의배경을녹색으로한다. Button ok = new Button("OK"); p.add(ok); // Button을 Panel 에포함시킨다. f.add(p); // Panel을 Frame 에포함시킨다. f.setvisible(true); [ 실행결과] 위의결과에서녹색으로표시된부분이 Panel 이다. Frame에는레이아웃매니저를사용하 지않았으므로 Panel 의위치와크기를지정해주어야했지만, Panel은기본적으로 FlowLayout을레이아웃매니저로사용하므로 Panel안에포함된버튼의위치와크기는

Chapter 13 AWT 와애플릿(Applet) 709 따로지정해주지않아도되었다. Button은 Panel에포함되어있는것이기때문에 Panel에지정된레이아웃매니저의영 향을받으며, Frame 의레이아웃매니저의영향을받지는않는다. [ 참고] 오른쪽그림은다음에배우게될 ScrollPane과비교하기위해서 Frame 의크기를줄여본것이다. 2.12 ScrollPane ScrollPane 은컨테이너이므로, 다른컴포넌트를포함시킬수있으나다른컨테이너들과는 달리단하나의컴포넌트만을포함시킬수있다. 제한된공간에서크기가큰컴포넌트를화면에보여줄수있도록하는데사용되며, 포함 된컴포넌트의크기가 ScrollPane 자신보다큰경우스크롤바를이용해서볼수있게해 준다. 메서드또는생성자 ScrollPane(int scrollbardisplaypolicy) ScrollPane() 설명 srollbardisplaypolicy - 아래값중의하나를지정한다. SCROLLBARS_ALWAYS - 스크롤바가항상보이게한다. SCROLLBARS_AS_NEEDED - 필요할때만보이게한다. SCROLLBARS_NEVER - 항상보이지않도록한다. ScrollPane 의객체를생성한다. [ 표13-13] ScrollPane의메서드 [ 예제13-14]/ch13/ScrollPaneTest.java import java.awt.*; class ScrollPaneTest { public static void main(string args[]) { Frame f = new Frame("ScrollPaneTest"); f.setsize(300, 200); ScrollPane sp = new ScrollPane(); Panel p = new Panel(); p.setbackground(color.green); // Panel의배경을 green 으로한다. p.add(new Button(" 첫번째")); // Button을 Panel 에포함시킨다. p.add(new Button(" 두번째")); p.add(new Button(" 세번째")); p.add(new Button(" 네번째")); sp.add(p); // Panel을 ScrollPane 에포함시킨다. f.add(sp); // ScrollPane을 Frame 에포함시킨다. f.setvisible(true);

710 Java의정석定石 2판 [ 실행결과] 이번예제에서는 4개의 Button을가진 Panel을 ScrollPane 에넣고, ScrollPane을 Frame 에넣었다. 위의결과를이전의예제13-13 의실행결과와비교해보자. Frame 의크기를줄였을때, 이전예제에서는컴포넌트들이가려져 Frame의크기를늘리기전까지는다시볼수없었 으나, 이번예제에서는 Frame 의크기를줄였을때, 자동적으로스크롤바가나타나서 Frame 의크기를변경하지않고도스크롤바를통해서가려진컴포넌트들을볼수있다. 2.13 Dialog Dialog 는주로화면에메시지창을보여주는데사용된다. 프로그램의실행중에사용자에 게에러가발생했음을알린다던가, 파일을삭제하기전에사용자로부터응답을받아야한 다던가하는데사용된다. Dialog 역시다른컴포넌트들을포함할수있는컨테이너이며, Frame과유사한모양을 하고있다. 메서드또는생성자 Dialog(Frame parent, String title, boolean modal) [ 표13-14] Dialog의메서드 설명 parent - 어떤 Frame 에속한것인지지정. title - Dialog의 titlebar에나타날 text지정 modal - Dialog를 modal( 필수응답) 로할것인지를결정. Dialog(Frame parent, String title) modal 을지정하지않으면, false 가된다. void show() void hide() void dispose() Dialog 가화면에나타나도록한다. Dialog 가화면에보이지않도록한다.( 메모리에는남아있다.) Dialog 를닫는다.( 화면에안보이게한후, 메모리에서제거) String gettitle() Dialog의 titlebar에나타난 text 를얻는다. void setmodal(boolean b) Dialog를 modal(true) 또는 modaless(false) 로한다. void setresizable(boolean resizable) 사용자에의해서 Dialog 의크기가변경가능/ 불가능하도록한다.( 기본적으로 Dialog 는크기변경이불가능하다.) [ 참고] hide() 는 Dialog 가화면에보이지않게할뿐이지메모리에서제거되는것은아니다. Dialog를다시사용하지않을것이라면 dispose() 를, 잠시안보이게만할것이라면 hide() 를사용하도록한다. [ 참고] show() 와 hide() 는 JDK1.5부터 deprecated 되었다. 대신 void setvisible(boolean b) 를사용하자.

Chapter 13 AWT 와애플릿(Applet) 711 Dialog 의생성자를보면, Dialog을사용하기위해서는하나의 Frame이 Dialog의부모 (parent) 로지정되어야한다. 상속관계의부모자식관계는아니고, 단순히 Dialog가어느 Frame 과관련된것인지를지정해주기위한것이다. Dialog가 modal( 필수응답) 인경우에는부모로지정된 Frame은 Dialog가사라지기전까 지는사용할수없게된다. 주로사용자로부터중요한확인을받아야할경우에사용되며, Dialog의 modal값을 false로설정한경우에는 Dialog가열려있더라도부모 Frame을사 용할수있다. [ 예제13-15]/ch13/DialogTest.java import java.awt.*; class DialogTest { public static void main(string args[]) { Frame f = new Frame("Parent"); f.setsize(300, 200); // parent Frame을 f 로하고, modal을 true로해서필수응답 Dialog 로함. Dialog info = new Dialog(f, "Information", true); info.setsize(140, 90); info.setlocation(50, 50); // parent Frame 이아닌, 화면이위치의기준이된다. info.setlayout(new FlowLayout()); Label msg = new Label("This is modal Dialog", Label.CENTER); Button ok = new Button("OK"); info.add(msg); info.add(ok); f.setvisible(true); info.setvisible(true); // Dialog 를화면에보이게한다. [ 실행결과] Dialog도 Frame과같이기본레이아웃매니저가 BorderLayout 이기때문에, FlowLayout 으로변경하였다. Dialog를 modal 로생성했기때문에, Dialog가열려있는동안은 Dialog 의부모(parent) 인 Frame 을사용할수없다. 위의예제에서 Dialog를 modal값을 false로 바꾼다음에 Frame 을사용할수있는지확인해보도록한다. Dialog에있는 OK 버튼을누르면, Dialog 가닫히도록해야하는데, OK버튼을눌렀을때 의이벤트처리가되어있지않기때문에 OK 버튼을눌러도아무일도일어나지않는다.

712 Java의정석定石 2판 다음예제는 OK버튼에이벤트처리를해서, OK버튼을누르면 Dialog 가닫히도록했다. 예 제를실행하여, Dialog가닫힌후에 parent Frame 이사용가능한지테스트해보자. [ 예제13-16]/ch13/DialogTest2.java import java.awt.*; import java.awt.event.*; // 이벤트처리를위해서추가해야한다. class DialogTest2 { public static void main(string args[]) { Frame f = new Frame("Parent"); f.setsize(300, 200); // parent Frame을 f 로하고, modal을 true로해서필수응답 Dialog 로함. final Dialog info = new Dialog(f, "Information", true); info.setsize(140, 90); info.setlocation(50, 50); // parent Frame 이아닌, 화면기준의위치 info.setlayout(new FlowLayout()); Label msg = new Label("This is modal Dialog", Label.CENTER); Button ok = new Button("OK"); ok.addactionlistener(new ActionListener() { public void actionperformed(actionevent e) { //OK 버튼을누르면수행됨. // info.setvisible(false); // Dialog 를안보이게한다. info.dispose(); // Dialog 를메모리에서없앤다. ); info.add(msg); info.add(ok); f.setvisible(true); info.setvisible(true); // Dialog 를화면에보이게한다. 이예제는 OK 버튼에익명클래스를이용해서이벤트를처리하는코드를추가한것이다. 앞으로이벤트처리에대해서자세히배울것이므로지금은예제를실행해보고그결과를 확인하는정도면충분하다. Dialog의 OK 버튼을눌렀을때, dispose() 를이용해서 Dialog를메모리에서제거할수도 있고, setvisible(false) 를이용해서일시적으로보이지않게할수도있다. 두가지방법중어느것을사용하던간에 은사용가능하게된다. Dialog 가화면에서보이지않게되며, Frame 2.14 FileDialog FileDialog는파일을열거나저장할때사용되는 Dialog 이다. 대부분의기능들이이미구 현되어있기때문에따로코드를추가하지않아도된다. 메서드또는생성자 FileDialog(Frame parent, String title, int mode) 설명 parent - 어떤 Frame 에속한것인지지정. title - FileDialog의 titlebar에나타날 text지정 mode - FileDialog.LOAD, FileDialog.SAVE 중하나선택

Chapter 13 AWT 와애플릿(Applet) 713 FileDialog(Frame parent, String title) mode 를생략하면, 디폴드로 FileDialog.LOAD 가사용된다. String getfile() FileDialog 에의해선택된파일의이름을얻는다. String getdirectory() FileDialog 에의해선택된파일의경로(path) 를얻는다. void setfile(string file) void setdirectory(string dir) FileDialog 에지정된파일을설정한다. FileDialog 에지정된디렉토리를설정한다. [ 표13-15] FileDialog의메서드 [ 참고] getdirectory() 과 getfile() 로선택한파일의전체경로를얻을수있다 [ 예제13-17]/ch13/FileDialogTest.java import java.awt.*; import java.awt.event.*; class FileDialogTest { public static void main(string args[]) { Frame f = new Frame("Parent"); f.setsize(300, 200); FileDialog fileopen = new FileDialog(f, " 파일열기", FileDialog.LOAD); f.setvisible(true); fileopen.setdirectory("c:\\jdk1.5"); fileopen.setvisible(true); // 파일을선택한다음, FileDialog 의열기버튼을누르면, // getfile() 과 getdirectory() 를이용해서파일이름과위치한디렉토리를얻을수있다. System.out.println(fileOpen.getDirectory() + fileopen.getfile()); [ 실행결과] setdirectory("c:\\jdk1.5") 를호출해서 FileDialog 가열렸을때, c:\jdk1.5디렉토리내 의파일들이보이게된다. 만일파일을선택하지않고취소버튼을누르면, getfile() 은 null 을반환한다. [ 참고] FileDialog.SAVE 를이용해서파일저장을위한프로그램을만들어보자.

714 Java의정석定石 2판 3. 그외의 AWT 클래스 지금까지 AWT의컴포넌트들에대해서알아봤는데이외에도 AWT에서사용되는클래스 들을몇가지더소개하겠다. 3.1 Font Component의 setfont(font f) 를이용하면, 컴포넌트에사용되는 text 의글자체(font) 를 원하는것으로지정할수있다. 그렇게하기위해서는먼저 Font 의인스턴스를생성해야하는데, Font의생성자는아래 와같다. 메서드또는생성자 Font(String name, int style, int size) 설명 name - 사용할폰트의이름. ( 예: "Serif") style - 폰트의스타일을지정한다. 보통체(Font.PLAIN), 굵은체 (Font.BOLD), 기울임체(Font.ITALIC), 굵은기울임체(Font.BOLD +Font.ITALIC) 이들중하나를선택. size - 폰트의크기 [ 표13-16] Font의생성자 위생성자의매개변수 style에사용되는 Font.BOLD, Font.PLAIN, Font.ITALIC은 Font 의 static 멤버인정수형상수이다. 그렇기때문에 Font.BOLD+Font.ITALIC처럼덧셈연 산이가능한것이다. BOLD 를예로들면, 실제소스인 Font.java에다음과같이선언되어 있다. public static final int BOLD = 1; JDK에서는아래의 5 가지폰트를기본적으로제공한다. 그외의다른종류의폰트를사용 했을때는사용된폰트가실행될컴퓨터에설치되어있어야만, 바른실행결과를얻을수 있다. Serif SansSerif Dialog DialogInput Monospaced 현재사용중인시스템에설치된 클래스를사용하면된다. Font의리스트를얻기위해서는 GraphicsEnvironment [ 참고] Monospaced 는모든문자의폭이일정한고정길이폭(Fixed width) 폰트이다. 즉, i와 l과같이폭이좁은문자들도 M, W 와같이폭이넓은문자들과같은폭으로표현된다.

Chapter 13 AWT 와애플릿(Applet) 715 [ 예제13-18]/ch13/FontList.java import java.awt.*; class FontList { public static void main(string[] args) { GraphicsEnvironment ge = null; ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); Font[] fonts = ge.getallfonts(); for(int i=0; i < fonts.length; i++) { System.out.println(fonts[i].getFontName()); [ 실행결과] Abadi MT Condensed Light Albertus Extra Bold Albertus Medium Albertus Medium Cursiva... 중간생략 [ 예제13-19]/ch13/FontTest.java import java.awt.*; class FontTest { public static void main(string args[]) { Frame f = new Frame("Font Test"); String abc = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; // A 부터 Z를내용으로갖는 Label 들을생성한다. Label abc1 = new Label(abc); Label abc2 = new Label(abc); Label abc3 = new Label(abc); Label abc4 = new Label(abc); Label abc5 = new Label(abc); // Serif 체이며, 크기가 20인 Font Font f1 = new Font("Serif", Font.PLAIN, 20); // 보통체 Font f2 = new Font("Serif", Font.ITALIC, 20); // 기울임체 Font f3 = new Font("Serif", Font.BOLD, 20); // 굵은체 Font f4 = new Font("Serif", Font.BOLD+Font.ITALIC, 20); // abc1.setfont(f1); // Label에새로운 Font 를적용한다. abc2.setfont(f2); abc3.setfont(f3); abc4.setfont(f4); f.setlayout(new FlowLayout()); f.add(abc1); f.add(abc2); f.add(abc3); 굵은기울임체

716 Java의정석定石 2판 f.add(abc4); f.add(abc5); f.setsize(400, 200); f.setvisible(true); [ 실행결과] Font와 setfont(font f) 를이용해서 Label에폰트를 Serif로설정하고 style을각각보통 체, 굵은체, 기울임체, 굵은기울임체로변화를주어비교할수있도록하였다. 마지막 Label은 setfont(font f) 로폰트를지정해주지않았기때문에자신이포함된컨 테이너(Frame) 에기본적으로설정되어있는폰트설정의영향을받았다. 3.2 Color Color 는색을표현하기위해사용되는클래스로써, 원하는색의 RGB값만알고있으면그 색을표현할수있는객체를생성하여사용할수있다. Color클래스내에는 blue, red, green, yellow 등자주쓰이는색 13가지가 static 멤버 변수로정의되어있어서색의 RGB 값을몰라도쉽게사용할수있다. 주로컴포넌트의배경색과전경색을설정하는 setforeground(color c), setbackground (Color c) 와같은메서드의매개변수로사용된다. 메서드또는생성자 Color(int r, int g, int b) Color(float r, float g, float b) 설명 r - red, g - green, b - blue r, g, b 모두 0~255 사이의정수값을갖는다. r - red, g - green, b - blue r, g, b 모두 0.0~1.0 사이의실수값을갖는다. Color(int r, int g, int b, int a) a - alpha값으로 0~255사이의정수값 Color(float r, float g, float b, float a) a - alpha값으로 0.0~1.0사이의실수값 [ 표13-17] Color의생성자 [ 참고] alpha 는색의불투명도를뜻한다. 값이클수록색이불투명해진다.

Chapter 13 AWT 와애플릿(Applet) 717 [ 예제13-20]/ch13/ColorTest.java import java.awt.*; class ColorTest { public static void main(string args[]) { Frame f = new Frame("Color Test"); f.setlayout(new GridLayout(14, 2)); Panel p1 = new Panel(); p1.setbackground(color.black); Panel p2 = new Panel(); p2.setbackground(color.blue); Panel p3 = new Panel(); p3.setbackground(color.cyan); Panel p4 = new Panel(); p4.setbackground(color.darkgray); Panel p5 = new Panel(); p5.setbackground(color.gray); Panel p6 = new Panel(); p6.setbackground(color.green); Panel p7 = new Panel(); p7.setbackground(color.lightgray); Panel p8 = new Panel(); p8.setbackground(color.magenta); Panel p9 = new Panel(); p9.setbackground(color.orange); Panel p10 = new Panel(); p10.setbackground(color.pink); Panel p11 = new Panel(); p11.setbackground(color.red); Panel p12 = new Panel(); p12.setbackground(color.white); Panel p13 = new Panel(); p13.setbackground(color.yellow); Panel p14 = new Panel(); p14.setbackground(new Color(50,100,100)); f.add(new Label("Color.black")); f.add(p1); f.add(new Label("Color.blue")); f.add(p2); f.add(new Label("Color.cyan")); f.add(p3); f.add(new Label("Color.darkGray")); f.add(p4); f.add(new Label("Color.gray")); f.add(p5); f.add(new Label("Color.green")); f.add(p6); f.add(new Label("Color.lightGray")); f.add(p7); f.add(new Label("Color.magenta")); f.add(p8); f.add(new Label("Color.orange")); f.add(p9); f.add(new Label("Color.pink")); f.add(p10); f.add(new Label("Color.red")); f.add(p11); f.add(new Label("Color.white")); f.add(p12); f.add(new Label("Color.yellow")); f.add(p13); f.add(new Label("Color(50, 100, 100)")); f.add(p14); f.setsize(250, 300); f.setvisible(true); [ 실행결과]

718 4. Java의정석定石 2판 메뉴만들기 4.1 메뉴를구성하는컴포넌트 Frame에메뉴를구성하기위해서는 사용한다. 이들의상속관계는다음과같다. Object MenuBar, Menu, MenuItem과같은컴포넌트들을 MenuComponent Component MenuItem MenuBar Menu CheckboxMenuItem PopupMenu [ 그림13-7] 메뉴관련컴포넌트의상속계층도 모든 AWT컴포넌트의조상이 Component인것처럼메뉴를구성하는컴포넌트들의조상 은 MenuComponent 이다. 폴더에폴더를담듯이 Menu에다시 Menu를담아서계층형으로메뉴를구성할수있으 며, 항상화면에나타나는최상위메뉴는 MenuBar에담고 MenuBar는다시 Frame에추 가함으로써메뉴작성을마치게된다. 메뉴를작성하는것은간단해서예제를보고나면쉽게이해가될것이다. [ 예제13-21]/ch13/MenuTest.java import java.awt.*; class MenuTest { public static void main(string args[]) { Frame f = new Frame("Frame with Menu"); f.setsize(300, 200); MenuBar mb = new MenuBar(); Menu mfile = new Menu("File"); MenuItem minew = new MenuItem("New"); MenuItem miopen = new MenuItem("Open"); Menu mothers = new Menu("Others"); // MenuItem이아니라 Menu임에주의 MenuItem miexit = new MenuItem("Exit"); mfile.add(minew); // Menu에 MenuItem 들을추가한다. mfile.add(miopen); mfile.add(mothers); // Menu에 Menu 를추가한다. mfile.addseparator(); // 메뉴분리선을넣는다.

Chapter 13 AWT 와애플릿(Applet) 719 mfile.add(miexit); MenuItem miprint = new MenuItem("Print..."); MenuItem mipreview = new MenuItem("Print Preview"); MenuItem misetup = new MenuItem("Print Setup..."); mothers.add(miprint); mothers.add(mipreview); mothers.add(misetup); Menu medit = new Menu("Edit"); Menu mview = new Menu("View"); Menu mhelp = new Menu("Help"); CheckboxMenuItem mistatusbar = new CheckboxMenuItem("Statusbar"); mview.add(mistatusbar); mb.add(mfile); // MenuBar에 Menu 를추가한다. mb.add(medit); mb.add(mview); mb.sethelpmenu(mhelp); // mhelp를 HelpMenu 로지정한다. f.setmenubar(mb); // Frame에 MenuBar 를포함시킨다. f.setvisible(true); [ 실행결과] 메서드또는생성자 설명 sethelpmenu(menu menu) 인자로넘겨받은 menu를 Help menu 로지정한다. addseparator() Menu 에분리선(Separator) 을추가한다. CheckboxMenuItem(String boolean status) name, CheckboxMenuItem(String name) name - CheckboxMenuItem에보여질 menu 이름. status - 값이 true 면, 체크된상태로생성된다. name - CheckboxMenuItem에보여질 menu 이름. status값을지정하지않으면기본적으로 false 값을갖는다. [ 표13-18] 예제13-21에사용된주요메서드 sethelpmenu() 에의해서 Help메뉴로지정된메뉴는 OS 마다다르게취급된다. 예를들어, SUN사의 Solaris OS에서는 Help메뉴로지정된메뉴는 MenuBar의맨오른쪽에따로위치 하게되지만, MS의윈도우OS에서는메뉴를 Help메뉴로지정해도특별히다르게다뤄지지 않는다.

720 Java의정석定石 2판 이예제에사용된컴포넌트들을종류에따라분류하면아래와같다. Menu - File, Edit, View, Help, Others MenuItem - New, Open, Print..., Print Preview, Print Setup..., Exit, CheckboxMenuItem - Statusbar MenuBar Menu Menu MenuItem Menu MenuItem [ 그림13-8] 메뉴컴포넌트간의포함관계 위의그림은 menu 관련컴포넌트들의기본구조를표현한것이다. 각클래스간의상속관 계를표현한것이아니라는것에주의하자. - MenuBar에는 Menu 만포함될수있다.(MenuItem 은포함시킬수없다.) - Menu에는 Menu와 MenuItem 이포함될수있다. - 계층형 menu를만들고자할때는 Menu에 Menu 를포함시키면된다. 아래의그림은예제에사용된메뉴의구조를표현한것이다. MenuBar File Edit View Help New Open Others Exit Statusbar Print... Print Print Preview... Setup... [ 그림13-9] 예제13-21의메뉴구성도

Chapter 13 AWT 와애플릿(Applet) 721 Menu(File) 아래에 Menu(Others) 를넣음으로써계층형메뉴가가능하도록했다. View Menu아래있는 Statusbar는 CheckboxMenuItem으로써 Checkbox처럼메뉴를클릭할 때마다메뉴앞에체크표시가설정되거나해제된다. 4.2 PopupMenu PopupMenu는 Frame에붙어있는고정적인 Menubar 와는달리, Frame내의어디서나마 우스의오른쪽버튼을누르면나타나는, 위치가고정되어있지않은메뉴이다. 여러분들은 이미 PopupMenu 에익숙해져있으며, 그편리함도잘알고있을것이다. [ 예제13-22]/ch13/PopupMenuTest.java import java.awt.*; import java.awt.event.*; // 이벤트처리를위해서추가했다. class PopupMenuTest { public static void main(string args[]) { final Frame f = new Frame("PopupMenu Test"); f.setsize(300, 200); final PopupMenu pmenu = new PopupMenu("Edit"); MenuItem micut = new MenuItem("Cut"); MenuItem micopy = new MenuItem("Copy"); MenuItem mipaste = new MenuItem("Paste"); pmenu.add(micut); // PopupMenu에 MenuItem 들을추가한다. pmenu.add(micopy); pmenu.add(mipaste); f.add(pmenu); // PopupMenu를 Frame 에추가한다. f.addmouselistener( new MouseAdapter() { // 익명클래스 public void mousepressed(mouseevent me) { // 오른쪽마우스버튼을누르면 PopupMenu 를화면에보여준다. if(me.getmodifiers() == me.button3_mask) pmenu.show(f, me.getx(), me.gety()); ); f.setvisible(true); [ 실행결과]

722 Java의정석定石 2판 예제를실행시킨후 Frame위에서마우스오른쪽버튼을누르면위의그림과같이 PopupMenu 가나타난다. 익명클래스를 main 메서드내에정의했기때문에, 익명클래스에서 Frame타입참조변수 f와 PopupMenu타입참조변수 pmenu를참조하기위해서 final 키워드를사용했다. [ 참고] 메서드내에정의된클래스에서는, 같은메서드내에선언된변수들(Local Variable) 중 final 키워드가붙은것들만참조가가능하다는것을기억하자. Frame에이벤트처리를해서 Frame 위에서마우스오른쪽버튼을누르면, PopupMenu가 나타나게했다. 그리고 getx(), gety() 는 Frame 내에서의마우스포인터의위치즉, Frame내에서의 x, y 좌표를얻는데사용되었다. [ 참고] PopupMenu에도 Menu 를포함시킴으로써계층형메뉴를구현할수있다. 5. 레이아웃매니저 AWT 프로그래밍에있어서화면구성을위해컨테이너내에컴포넌트를적절하게배치한 다는것은그리쉬운일이아니다. 하지만레이아웃매니저를이용하면컨테이너에컴포 넌트배치를손쉽게처리할수있다. AWT 에서제공하는레이아웃매니저의종류와사용방법에대해서알아보도록하자. 5.1 레이아웃매니저를이용한컴포넌트배치 레이아웃매니저는컨테이너에포함된컴포넌트들의배치(Layout) 를자동적으로관리해주는일을한다. 컨테이너에새로운컴포넌트가추가되거나컨테이너의크기가변경되었을경우, 컨테이너에포함된컴포넌트들의재배치를레이아웃매니저가자동적으로처리해주기때문에프로그래머가컴포넌트의재배치를위한코드를작성하지않아도된다. [ 참고] 기존의 GUI프로그래밍에서는컨테이너의크기가변경될때마다컨테이너에포함된컴포넌트들을재배치하는코드를프로그래머가직접작성해야한다. 이처럼컨테이너에컴포넌트들을효율적으로배치하게위해서는레이아웃매니저의사용 이필수적이라고할수있다. AWT에서는 5 가지종류의레이아웃매니저를제공하며, 그종류는다음과같다. - BorderLayout - FlowLayout - GridLayout - CardLayout - GridbagLayout [ 참고] 여기서는 GridbagLayout을제외한나머지 4 가지레이아웃매니저에대해서알아볼것이다.

Chapter 13 AWT 와애플릿(Applet) 723 컨테이너에는단하나의레이아웃매니저만을설정할수있으며모든컨테이너는따로설 정하지않아도기본적으로레이아웃매니저가지정되어있다. 각컨테이너별기본레이아웃매니저는다음과같다. 컨테이너별기본레이아웃매니저 FlowLayout - Panel, Applet BorderLayout - Window, Dialog, Frame 자, 이제레이아웃매니저를하나씩살펴보도록하자. 5.2 BorderLayout BorderLayout은컨테이너를 North, South, East, West, Center 모두 5개의영역으로나 누고, 각영역에하나의컴포넌트만을배치할수있도록한다. 그래서한영역에여러개 의컴포넌트를배치하면, 마지막에추가한컴포넌트만보이게된다. 한영역에하나이상의컴포넌트를넣기위해서는 Panel 을이용해야한다. Panel에원하 는컴포넌트들을넣은다음, BorderLayout의한영역에다시이 Panel 을넣으면된다. BorderLayout은컨테이너인 Window, Frame, Dialog의기본 Layout 이다. 즉, 이컨테 이너들의레이아웃매니저는따로설정하지않아도생성되어질때부터이미 BorderLayout 으로설정되어있다는것이다. 메서드또는생성자 BorderLayout(int hgap, int vgap) 설명 각영역사이에간격이있는 BorderLayout 을생성한다. hgap - 각영역의사이에간격을준다.( 좌우) vgap - 각영역의사이에간격을준다.( 위아래) BorderLayout() 영역사이에간격이없는 BorderLayout 을생성한다. add(string name, Component c) 또는 add(component c, String name) c - 추가하려는컴포넌트 name- "North", "South", "East", "West", "Center" 중의하나또는 BorderLayout.NORTH, BorderLayout.SOUTH, BorderLayout.EAST,BorderLayout.WEST, BorderLayout.CENTER 중의하나 [ 표13-19] BorderLayout의메서드 [ 예제13-23]/ch13/BorderLayoutTest.java import java.awt.*; class BorderLayoutTest { public static void main(string args[]) { Frame f = new Frame("BorderLayoutTest"); f.setsize(200, 200); // Frame은기본적으로 BorderLayout로설정되어있으므로따로설정하지않아도됨 f.setlayout(new BorderLayout()); Button north = new Button("North"); Button south = new Button("South");

724 Java의정석定石 2판 Button east = new Button("East"); Button west = new Button("West"); Button center = new Button("Center"); // Frame의 5개의각영역에 Button 을하나씩추가한다. f.add(north, "North"); // f.add("north",north); 와같이쓸수도있다. f.add(south, "South"); // South의대소문자정확히 f.add(east, "East"); // East 대신, BorderLayout.EAST 사용가능 f.add(west, "West"); f.add(center, "Center"); f.setvisible(true); [ 실행결과] 예제를실행시킨후 Frame 의크기를좌우로그리고상하로변경해본것이다. 이때의변 화를잘살펴보자. Frame의크기를상하로늘렸을때 - West, Center, East영역의길이만상하로늘어나고 North와 South영역에는아무런변화 가없다. Frame의크기를좌우로늘렸을때 - North, Center, South영역의길이만좌우로늘어나고 West와 East영역에는아무런변화 가없다. [ 참고] 컨테이너의크기가변경되어도 North와 South 영역에배치된컴포넌트의높이(height) 와 East와 West영역에배치된컴포넌트의너비(width) 는적절한크기(preferred size) 를그대로유지한다. [ 참고] preferred size - 컴포넌트들이생성될때지정된값과설정된폰트의크기등의정보를바탕으로계산된크기. BoderLayout과 FlowLayout은컴포넌트배치에컴포넌트의 preferred size 를사용한다.

Chapter 13 AWT 와애플릿(Applet) 725 BorderLayout 의각영역에컴포넌트를추가할때는, 컨테이너에 add(component c, String area) 또는 add(string area, Component c) 를사용한다. 5개의영역을모두채워 줘야하는것은아니고필요한영역에만컴포넌트를추가할수있다. 아래의그림들은 BorderLayout 으로가능한컴포넌트배치의몇가지예를보여준다. North Center East West Center West Center South [ 그림13-10] BorderLayout으로구성가능한화면의예 5.3 FlowLayout FlowLayout 은컴포넌트들이추가되는순서에따라왼쪽에서오른쪽으로이어져나가며, 공간이부족하면, 아랫줄에추가된다. 이것은마치글자를입력하면왼쪽에서오른쪽으로진행해나가며, 한라인의끝에다다 르면, 다음라인의처음부터글자가입력되는워드프로세서에서의문자입력과매우유사 하다. 또한컴포넌트의정렬에있어서도워드프로세서에서와같이왼쪽정렬, 오른쪽정렬, 그 리고가운데정렬이가능하다. 메서드또는생성자 FlowLayout(int align, int hgap, int vgap) FlowLayout(int align) 설명 align - 컴포넌트들의정렬방법을지정한다. FlowLayout.LEFT( 왼쪽정렬), FlowLayout.CENTER( 가운데정렬) FlowLayout.RIGHT( 오른쪽정렬) 중하나를지정한다. hgap - 각컴포넌트간의사이에간격을준다.( 좌우) vgap - 각컴포넌트간의사이에간격을준다.( 위아래) hgap과 vgap이 5픽셀인 FlowLayout 을생성한다. align - 컴포넌트들의정렬방법을지정한다. FlowLayout() 가운데정렬이면서 hgap과 vgap이 5픽셀인 FlowLayout 을생성한다. [ 표13-20] FlowLayout의생성자 [ 예제13-24]/ch13/FlowLayoutTest.java import java.awt.*; class FlowLayoutTest { public static void main(string args[]) { Frame f = new Frame("FlowLayoutTest"); f.setsize(250, 100); f.setlayout(new FlowLayout(FlowLayout.LEFT)); 왼쪽정렬의생성 // FlowLayout

726 Java의정석定石 2판 f.add(new Button(" 첫번째")); f.add(new Button(" 두번째")); f.add(new Button(" 세번째")); f.add(new Button(" 네번째")); f.add(new Button(" 다섯번째")); f.setvisible(true); [ 실행결과] 위의결과에서도볼수있듯이, Frame의크기를변경함에따라컴포넌트들의배치가달 라지는것을볼수있다. 컴포넌트들이추가된순서와 Frame의크기를늘렸을때와줄였 을때의컴포넌트들의달라진배치를유심히살펴보기바란다. 컨테이너인 Frame 의크기가변해도, 포함된컴포넌트들의크기는변하지않는데, 레이 아웃매니저가 FlowLayout으로설정된컨테이너에추가된컴포넌트들은컨테이너의크 기가변해도컴포넌트의크기는영향을받지않고배치에만영향을받는다. 이때컴포넌 트들은적절한크기(preferred size) 를유지하게된다. 5.4 GridLayout GridLayout 은컨테이너를테이블처럼행과열로나누어컴포넌트를배치한다. 여기에추가되는컴포넌트들은모두같은크기로나누어지며, 컨테이너의크기를변경하면각영역이모두같은비율로커지거나작아지는성질을갖고있다. 메서드또는생성자 GridLayout(int row, int col, int hgap, int vgap) GridLayout(int row, int col) [ 표13-21] GridLayout 의생성자. 설명 영역들간의사이에간격이있는 GridLayout 을생성한다. row - 컨테이너를몇개의행(row) 으로나눌것인지적는다. col - 컨테이너를몇개의열(column) 로나눌것인지적는다. hgap - 각영역간의사이에간격을준다.( 좌우) vgap - 각영역간의사이에간격을준다.( 위아래) 영역들간의사이에간격이없는 GridLayout 을생성한다. row - 컨테이너를몇개의행(row) 으로나눌것인지적는다. col - 컨테이너를몇개의열(column) 로나눌것인지적는다.

Chapter 13 AWT 와애플릿(Applet) 727 [ 예제13-25]/ch13/GridLayoutTest.java import java.awt.*; class GridLayoutTest { public static void main(string args[]) { Frame f = new Frame("GridLayoutTest"); f.setsize(150, 150); f.setlayout(new GridLayout(3, 2)); // 3행 2 열의테이블을만든다. f.add(new Button("1")); // 추가되는순서대로 Button 에번호를붙였다. f.add(new Button("2")); f.add(new Button("3")); f.add(new Button("4")); f.add(new Button("5")); f.add(new Button("6")); f.setvisible(true); [ 실행결과] 위의결과를보면, Frame에 Button이추가될때어떤순서로 GridLayout의영역에추가 되는지쉽게알수있을것이다. 첫번째행의열들을모두채운후에그아래행의열들 을채운다. 이와같은방식으로컴포넌트들이추가되게된다. 그리고, 오른쪽의그림은실행후 Frame 의크기를늘린것인데, 늘어난후에도각영역 의 Button 들이모두같은크기를유지하는것을알수있다. [ 참고] GridbagLayout은 GridLayout 과같이컨테이너를열과행으로나누어컴포넌트들을배치할수있다. 각영역은서로다른크기로지정될수있으며, 인접한열또는행으로의확장이가능하다. 마치 HTML문서에서의 Table의레이아웃을설정하는것과비슷하다.

728 Java의정석定石 2판 5.5 CardLayout CardLayout은여러화면을슬라이드처럼바꿔가며보여줄수있다. 즉, 여러개의컨테 이너를 CardLayout 에추가한다음, 순서대로또는임의의컨테이너를선택해서보여줄 수있다. 설치프로그램과같이단계별로다른화면으로이동하는경우에사용하면유용할 것이다. 메서드또는생성자 CardLayout(int hgap, int vgap) 설명 hgap - 컨테이너와 CardLayout 사이에간격을준다.( 수평) vgap - 컨테이너와 CardLayout 사이에간격을준다.( 수직) CardLayout() 컨테이너와간격이없는 CardLayout 을생성한다. add(container parent, String name) show(container parent, String name) first(container parent) last(container parent) previous(container parent) next(container parent) name - 주어진이름으로, parent - 지정된컨테이너에추가한다. 주어진이름의컴포넌트를컨테이너에보여준다. name - 나타낼컨테이너의이름( 추가할때사용한이름) parent - 컴포넌트가보여질컨테이너 parent - 보여준다. parent - 보여준다. 지정된컨테이너에첫번째로추가된컴포넌트를 지정된컨테이너에마지막으로추가된컴포넌트를 지정된컨테이너에현재보이는컴포넌트보다이전에추가된것을보여준다.( 현재보이는것이첫번째것이면, 제일마지막것이나타나게된다.) 지정된컨테이너에현재보이는컴포넌트보다다음에추가된것을보여준다.( 현재보이는것이마지막것이면, 제일첫번째것이나타나게된다.) [ 표13-22] CardLayout의메서드 [ 예제13-26]/ch13/CardLayoutTest.java import java.awt.*; import java.awt.event.*; class CardLayoutTest { public static void main(string args[]) { final Frame f = new Frame("CardLayoutTest"); final CardLayout card = new CardLayout(10, 10); f.setlayout(card); Panel card1= new Panel(); card1.setbackground(color.lightgray); card1.add(new Label("Card 1")); Panel card2= new Panel(); card2.add(new Label("Card 2")); card2.setbackground(color.orange); Panel card3= new Panel(); card3.add(new Label("Card 3")); card3.setbackground(color.cyan); f.add(card1, "1"); // Frame에 card1 을 "1" 이라고이름붙여추가한다. f.add(card2, "2");

Chapter 13 AWT 와애플릿(Applet) 729 f.add(card3, "3"); class Handler extends MouseAdapter { public void mouseclicked(mouseevent e) { // 마우스오른쪽버튼을눌렀을때 if(e.getmodifiers() == e.button3_mask) { card.previous(f); // CardLayout의이전 Panel 을보여준다. else { card.next(f); // CardLayout의다음 Panel 을보여준다. // class Handler card1.addmouselistener(new Handler()); card2.addmouselistener(new Handler()); card3.addmouselistener(new Handler()); f.setsize(200, 200); f.setlocation(200, 200); f.setvisible(true); card.show(f,"1"); // Frame에추가된 Component 중이름이 "1" 인것을보여준다. [ 실행결과] 위의예제는 Frame의레이아웃매니저를 CardLayout 으로하고, CardLayout에 3개의 Panel 을추가하였다. 실행하면첫번째 Panel(Card 1) 이보이도록했으며, Panel위를마 우스왼쪽버튼으로클릭하면, 두번째 Panel(Card 2) 이보이도록했다. 또마우스오른 쪽버튼을누르면, 클릭한 Panel 보다이전에있는 Panel 이보이도록했다. [ 예제13-27]/ch13/Calc.java import java.awt.*; import java.awt.event.*; class Calc { public static void main(string args[]) { Frame f = new Frame(" 계산기"); TextField tf = new TextField("0"); tf.seteditable(false); f.setsize(190, 160);

730 Java의정석定石 2판 f.setlocation(300,300); f.add("north", tf); Panel numpanel = new Panel(); Button[] numbuttons = null; numpanel.setlayout(new GridLayout(4, 5, 4, 4)); numpanel.setbackground(color.lightgray); f.add("center", numpanel); String numstr[] = { "7", "8", "9", "/", " CE ", "4", "5", "6", "*", "BS", "1", "2", "3", "-", "1/x", "0", "+/-", ".", "+", "=" ; numbuttons = new Button[numStr.length]; for(int i=0;i<numstr.length;i++) { numbuttons[i] = new Button(numStr[i]); numbuttons[i].setforeground(color.blue); numpanel.add(numbuttons[i]); f.setresizable(false); f.setvisible(true); [ 실행결과] Frame(BorderLayout) Panel(GridLayout) 이번예제에서는 BorderLayout과 GridLayout, 이두개의레이아웃매니저를이용해서 간단한계산기를만들어보았다. 이벤트처리를하지않았기때문에아무런기능도못하 지만, Panel 을이용한조금복잡한레이아웃으로구성되어있다. Frame은 North와 Center 두영역으로만있는 BorderLayout 으로설정하고, Frame의 Center영역에 4행 5열의 GridLayout으로구성된 Panel 을추가한다. 심지어는 Panel을 Panel에넣는방식으로더다양하고복잡한 Layout의화면을만들수 있다. 계산결과를보여주는창을 TextField 로하였는데, TextField는 text의정렬이안되 기때문에오른쪽이아닌왼쪽에 '0' 이있다. 이것을개선하기위해서는 Label을사용하던 가 Swing의 JTextField 를사용하면된다. Swing과 AWT의컴포넌트간에는서로섞어쓰 지않는것이좋지만, 이런경우에는별문제없다. [ 참고] 많은수의 Button 을가지고작업을해야하기때문에배열과반복문을이용하여코드를간단히했다. 이렇게하는것이 Button 의이름또는순서를바꾸는데더용이하다.

Chapter 13 AWT 와애플릿(Applet) 731 6. 이벤트처리(event handling) 6.1 이벤트(event) 란? 이벤트(Event) 란, 사용자또는프로그램코드에의해서발생할수있는사건을말한다. 예 를들면, 사용자가마우스를움직이거나클릭할때, 키보드를눌렀을때, 또는 Frame의 크기를변경할때이벤트가발생한다. 이벤트소스 종류 (Event Source, 이벤트발생지) 이벤트핸들러 (Event Handler, 이벤트처리기) 이벤트리스너 (Event Listener, 이벤트감지기) 설명 이벤트가발생한컴포넌트. 사용자가 Button을눌렀을때 이벤트가발생하고, Button은이이벤트의이벤트소스가 된다. 이벤트가발생했을때실행될코드를구현해놓은클래스 이벤트를감지하고처리한다. 이벤트핸들러를이벤트 리스너로이벤트소스에연결해야이벤트가발생했을때 이벤트가처리된다. [ 표13-23] 이벤트관련용어설명 이벤트에대한수행코드를작성하여이벤트소스에이벤트리스너(Event Listener) 로등 록하는것을이벤트처리(Event handling) 라고한다. 이벤트가발생하더라도그에대한 이벤트처리를하지않으면, 아무일도일어나지않는다. 사실사용자가 AWT 프로그램을사용하면서행하는모든동작은이벤트를발생시킨다. 단지그에대한이벤트처리가되어있지않아서이벤트가발생한사실을사용자가알지 못하는것이다. 6.2 이벤트의발생과처리 이벤트가발생하면해당이벤트클래스의인스턴스가생성된다.(ActionEvent가발생하면 ActionEvent 인스턴스가생성된다). 그다음에이벤트를처리할 Listener( 이벤트리스너) 가이벤트소스에등록되어있는지확인해서, 등록된 Listener중에서발생한이벤트를처 리할 Listener 가있으면, 이 Listener 가이벤트를처리하게된다. 반대로발생한이벤트를 처리할 Listener 가등록되어있지않으면, 아무일도일어나지않는다. 이벤트의발생에서부터처리까지의과정에대해서알아봤는데, 예외처리와유사하다는느 낌을많이받았을것이다. 예외발생시에해당하는종류의예외클래스의인스턴스가생 성되는점그리고, 예외가발생한곳에서발생한예외의종류와일치하는 catch 블럭( 이벤 트에서는 Listener) 이처리하는점, 예외발생시생성된객체를 catch블럭내에서사용 가능하다는점등처리방법이서로많이닮아있으므로이벤트처리를예외처리와비교해 보면보다쉽게이해할수있을것이다. [ 참고] 예외처리와이벤트처리의차이점은, 이벤트는처리해주지않아도아무런문제가되지않는다는것이다.

732 Java의정석定石 2판 6.3 이벤트처리방법 AWT프로그램실행중에사용자의어떠한동작에의해서이벤트가발생했을때, 이에대 해적절한작업을수행되도록하는것을이벤트처리(Event handling) 이라고한다. 예제13-1에서 Frame 의닫기버튼을눌러도아무런일도일어나지않는이유는, 이이 벤트가발생했을때작업을수행하는코드를작성하지않았기때문이다. 이예제에이벤트처리를추가하여닫기버튼을눌렀을때 [ 예제13-28]/ch13/FrameTest3.java import java.awt.*; import java.awt.event.*; class FrameTest3 { public static void main(string args[]) { Frame f = new Frame("Login"); // Frame 객체를생성한다. f.setsize(300, 200); // Frame 의크기를설정한다. Frame 이닫히도록하겠다. // EventHandler클래스의객체를생성해서 Frame의 WindowListener 로등록한다. f.addwindowlistener(new EventHandler()); f.setvisible(true); // 생성한 Frame 을화면에보이도록한다. class EventHandler implements WindowListener { public void windowopened(windowevent e) { public void windowclosing(windowevent e) { // Frame 의닫기버튼을눌렀을때호출된다. e.getwindow().setvisible(false); // Frame을화면에서보이지않도록하고 e.getwindow().dispose(); // 메모리에서제거한다. System.exit(0); // 프로그램을종료한다. public void windowclosed(windowevent e) { // 아무내용도없는메서드구현 public void windowiconified(windowevent e) { public void windowdeiconified(windowevent e) { public void windowactivated(windowevent e) { public void windowdeactivated(windowevent e) { [ 실행결과] 이예제를실행시킨후, Frame 의오른쪽맨위의닫기버튼을누르면, 예제13-1과는달 리 Frame 이닫히게될것이다. 그이유는, 닫기버튼을누르는이벤트가발생했을때 Frame 을닫는작업을하는코드를추가했기때문이다.

Chapter 13 AWT 와애플릿(Applet) 733 이벤트처리방법 1. 표 13-25 에있는메서드중에서필요한것을찾는다. windowclosing(windowevent we) 2. 선택한메서드가속해있는인터페이스를구현하는클래스를작성한다.( 표13-24 참고) class EventHandler implements WindowListener { public void windowclosing(windowevent e) { /* 코드작성 */... 3. 위에서구현한클래스의인스턴스를생성해서이벤트소스에 Listener 로등록한다. f.addwindowlistener(new EventHandler()); [ 참고] Listener등록에필요한메서드는표13-27 을참고하자. EventHandler클래스는 WindowListener인터페이스를구현해야하므로 WindowListener인 터페이스에정의되어있는모든추상메서드의몸통(body) 부분을만들어주어야만한다. 그래서, 내용은없지만메서드의몸통을만들어주었다. 이런메서드들은이벤트가발생하 여호출되어도실행될문장이하나도없기때문에아무일도하지않고바로종료된다. class EventHandler implements WindowListener { public void windowopened(windowevent e) { public void windowclosing(windowevent e) { e.getwindow().setvisible(false); e.getwindow().dispose(); System.exit(0); //Frame 의닫기버튼을누르면호출된다. //Frame을화면에서보이지않도록하고 // 메모리에서제거한다. // 프로그램을종료한다. public void windowclosed(windowevent e) { // 아무내용도없는메서드구현 public void windowiconified(windowevent e) { public void windowdeiconified(windowevent e) { public void windowactivated(windowevent e) { public void windowdeactivated(windowevent e) { windowclosing메서드는 Frame의닫기버튼을눌렀을때호출되므로어플리케이션을종료하는코드를추가했다. Frame 의닫기버튼을눌렀을때, 그이후의진행과정은다음과같다. 사용자가 Frame 의닫기버튼을누르면, 1. WindowEvent 가발생하고(WindowEvent 의인스턴스가생성됨), 2. Frame에 WindowListener로등록되어있는이벤트핸들러의 windowclosing메서드를 호출한다. 이메서드내에서는이벤트발생시생성된 WindowEvent인스턴스의참조를 사용할수있어서 WindowsEvent 인스턴스의메서드들을사용할수있다.

734 Java의정석定石 2판 이벤트인터페이스메서드 ActionEvent ActionListener actionpeformed(actonevent ae) ComponentEvent MouseEvent ComponentListener MouseMotionListener MouseListener componentmoved(actonevent ae) componenthidden(actonevent ae) componentresized(actonevent ae) componentshown(actonevent ae) mousedragged(mouseevent me) mousemoved(mouseevent me) mousepressed(mouseevent me) mousereleased(mouseevent me) mouseentered(mouseevent me) mouseexited(mouseevent me) mouseclicked(mouseevent me) MouseWheelEvent MouseWheelListener mousewheelmoved(mousewheelevent e) KeyEvent KeyListener keypressed(keyevent ke) keyreleased(keyevent ke) keytyped(keyevent ke) TextEvent TextListener textvaluechanged(textevent te) FocusEvent FocusListener focusgained(focusevent fe) focuslost(focusevent fe) ItemEvent ItemListener itemstatechanged(itemevent ie) AdjustmentEvent AdjustmentListener adjustmentvaluechanged(adjustmentevent ae) WindowEvent ContainerEvent WindowListener WindowFocusListener windowclosing(windowevent we) windowopened(windowevent we) windowiconified(windowevent we) windowdeiconified(windowevent we) windowclosed(windowevent we) windowactivated(windowevent we) windowdeactivated(windowevent we) windowgainedfocus(windowevent e) windowlostfocus(windowevent e) WindowStateListener windowstatechanged(windowevent e) ContainerListener componentadded(containerevent ce) componentremoved(containerevent ce) [ 표13-24] Event의종류와관련인터페이스 [ 참고] MouseWheelListener, WindowFocusListener, WindowStateListener는 JDK 1.4 부터추가되었다.

Chapter 13 AWT 와애플릿(Applet) 735 메서드 actionpeformed(actonevent ae) componentmoved(actonevent ae) componenthidden(actonevent ae) componentresized(actonevent ae) componentshown(actonevent ae) mousedragged(mouseevent me) mousemoved(mouseevent me) mousepressed(mouseevent me) mousereleased(mouseevent me) mouseentered(mouseevent me) mouseexited(mouseevent me) mouseclicked(mouseevent me) mousewheelmoved(mousewheelevent e) keypressed(keyevent ke) keyreleased(keyevent ke) keytyped(keyevent ke) 호출시기 Button 을클릭했을때, Menu 를클릭했을때, TextField에서 Enter 키를눌렀을때, List의 item하나를선택하여더블클릭했을때 컴포넌트가이동되었을때 컴포넌트가화면에보이지않게되었을때 컴포넌트의크기가변경되었을때 컴포넌트가화면에보일때 마우스버튼을누른채로마우스를움직였을때 마우스포인터를이동시킬때 마우스버튼을눌렀을때 마우스버튼을떼었을때 마우스포인터가이벤트소스의영역안으로들어왔을때 마우스포인터가이벤트소스의영역안에서밖으로이동할때 마우스버튼을눌렀다가떼었을때 마우스의휠을움직였을때 키보드의키를눌렀을때 키보드의키를떼었을때 키보드의키를눌렀다떼었을때 textvaluechanged(textevent te) TextField 또는 TestArea의내용이변경되었을때 focusgained(focusevent fe) 이벤트소스로 focus가이동했을때 focuslost(focusevent fe) itemstatechanged(itemevent ie) adjustmentvaluechanged(adjustment Event ae) windowopened(windowevent we) windowclosing(windowevent we) 이벤트소스가갖고있던 focus가다른컴포넌트로이동했을때 Checkbox, CheckboxItem, List, Choice의 status가변경되었을때 (selected unselected) Scrollbar 의값이변경되었을때 윈도우가열렸을때 윈도우가닫힐때( 닫기버튼을눌렀을때) windowclosed(windowevent we) 윈도우가닫혔을때(dispose() 가호출되었을때) windowiconified(windowevent we) windowdeiconified(windowevent we) windowactivated(windowevent we) windowdeactivated(windowevent we) windowgainedfocus(windowevent e) windowlostfocus(windowevent e) windowstatechanged(windowevent e) componentadded(containerevent ce) componentremoved(containerevent ce) 윈도우가최소화( 아이콘화) 되었을때 윈도우가최소화상태에서다시원래크기로되었을때 윈도우가활성화되었을때 윈도우가비활성화되었을때 윈도우가포커스를얻을때 윈도우가포커스를잃었을때 윈도우의상태가변했을때 컨테이너에컴포넌트가추가되었을때 컨테이너에컴포넌트가제거되었을때 [ 표13-25] 이벤트리스너를 Component 에추가/ 제거하는메서드 [ 참고] 표13-25에언급된윈도우는컨테이너인 Window 와그자손들(Frame, Dialog, FileDialog) 을뜻한다.

736 Java의정석定石 2판 ActionEvent 는고수준이벤트로컴포넌트에정의된동작이수행되었을때발생한다. 예 를들어버튼 (Button) 을마우스로클릭하거나, 버튼이포커스(focus) 를가졌을때스페이 스바를입력하면눌러진다. 이때 MouseEvent나 KeyEvent가발생하는것이아니라 ActionEvent 가발생한다. 실제로는 MouseEvent나 KeyEvent가발생하지만최종적으로 는 ActionEvent 가발생한것으로처리된다. 그래서 ActionListener의 actionperformed(actionevent ae) 에버튼이눌러졌을때수 행될코드를작성해야한다. ActionEvent가발생하는경우 - Button이눌러졌을때 - Menu를클릭했을때 - TextField에서 Enter키를눌렀을때 - List의 item하나를선택하여더블클릭했을때 이렇게하면버튼을누르는여러가지방법이존재하더라도 에대한처리만하면된다는장점이있다. ActionEvent가발생하고이 MS윈도우와같은 GUI OS에서는여러윈도우가열려있어도그중의하나만사용자가작 업을할수있다. 현재작업중인윈도우( 여러윈도우중에서가장위에나타나는윈도우) 를활성윈도우(active window) 라고하며, 사용자가다른작업을위해다른윈도우를선택 하면, 이전에작업중이던윈도우는비활성화(deactivated) 된다. 다음그림은이벤트관련클래스간의상속계층도를그린것이다. AWT이벤트의최고조상 은 AWTEvent 인것을알수있다. 각이벤트간의상속관계가중요한것은아니지만사용자이벤트를만들때참고하자. Object ActionEvent EventObject AdjustmentEvent ContainerEvent AWTEvent ComponentEvent FocusEvent ItemEvent InputEvent KeyEvent TextEvent WindowEvent MouseEvent [ 그림13-11] Event의상속계층도 [ 참고] 이벤트관련클래스는 java.awt.event 패키지에속한다.

Chapter 13 AWT 와애플릿(Applet) 737 try-catch구문의 catch 블럭내에서발생한예외의인스턴스를참조할수있는것처럼, 각 메서드에서는발생한 시생성된 Event 의인스턴스에대한참조를사용할수있으므로, 이벤트발생 Event 인스턴스의메서드들을사용할수있다는것을다시한번확인하자. ActionEvent 메서드 설명 String getactioncommand() 이벤트의 ActionCommand 를반환한다. int getmodifiers() 이벤트가발생때누르고있던특수키를반환한다. long getwhen() 이벤트가발생한시간을 long 값으로반환한다. AdjustmentEvent Adjustable getadjustable() 이벤트소스를반환한다. int getadjustmenttype() 값을변경시킨방법을알려준다. int getvalue() 이벤트발생시의 ( 스크롤바의) 값을반환한다. boolean getvalueisadjusting() 값이변경되고있는중인지를알려준다. ComponentEvent Component getcomponent() 이벤트소스를반환한다. ContainerEvent Component getchild() 컨테이너에추가/ 삭제된컴포넌트를반환한다. Container getcontainer() 이벤트소스를반환한다. FocusEvent Component getoppositecomponent() 포커스를잃은컴포넌트를반환한다. ItemEvent Object getitem() 이벤트가발생한 item 을반환한다. ItemSelectable getitemselectable() 이벤트소스를반환한다. int getstatechange() KeyEvent char getkeychar() 눌러진키를반환한다. Item 의상태( 선택/ 선택해제상태) 를반환한다. int getkeycode() 눌러진키의코드를반환한다. String getkeymodifierstext(int modifiers) String getkeytext(int keycode) MouseEvent 눌러진특수키(Alt, Ctrl) 또는특수키조합을설명하는문자열을반환한다. 눌러진키를한다. int getclickcount() 마우스를클릭한회수를반환한다. Point getpoint() 이벤트가일어난위치를반환한다. HOME, F1과같이키를설명하는문자열로반환 int getx() 이벤트가일어난위치의 x 좌표를반환한다. int gety() 이벤트가일어난위치의 y 좌표를반환한다. MouseWheelEvent int getscrollamount() 스크롤되어야하는양(amount) 을반환한다. int getscrolltype() 어떤스크롤타입에의해이벤트가발생했는지알려준다. int getunitstoscroll() 단위당스크롤해야하는양을반환한다. int getwheelrotation() 마우스휠이이동한방향을알려준다. WindowEvent int getnewstate() 윈도우의현재상태를반환한다.

738 Java의정석定石 2판 int getoldstate() 윈도우의이전상태를반환한다. Window getoppositewindow() 이벤트발생전에포커스를가졌던윈도우를반환한다. Window getwindow() 이벤트소스를반환한다. 모든이벤트공통 Object getsource() 이벤트소스를반환한다.(EvnetObject 에정의) String paramstring() [ 표13-26] 각 Event의주요메서드 [ 참고] EventObject는 java.util 패키지에, AWTEvent는 java.awt 패키지에포함되어있다. 다음은이벤트소스( 컴포넌트) 에 Listener 를추가또는제거하는메서드를정리한것이다. 이메서드들은 Listener의이름에 add 또는 remove 를붙여서만들어졌다. 표의맨오른쪽의이벤트소스는 Listener를추가할수있는컴포넌트인데 Component 는 Component 자손이대상에포함되며, Window는그자손인 Frame, Panel 등이포함됨 을의미한다. 이벤트에관련된정보를문자열로반환한다.(AWTEvent에정의 ) Listener Listener 를추가 / 제거때사용하는메서드이벤트소스 ActionListener AdjustmentListener ComponentListener ContainerListener FocusListener ItemListener KeyListener MouseListener MouseMotionListener TextListener WindowListener WindowFocusListener WindowStateListener void addactionlistener(actionlistener l) void removeactionlistener(actionlistener l) void addadjustmentlistener(adjustmentlistener l) void removeadjustmentlistener(adjustmentlistener l) void addcomponentlistener(componentlistener l) void removecomponentlistener(componentlistener l) void addcontainerlistener(containerlistener l) void removecontainerlistener(containerlistener l) void addfocuslistener(focuslistener l) void removefocuslistener(focuslistener l) void additemlistener(itemlistener l) void removeitemlistener(itemlistener l) void addkeylistener(keylistener l) void removekeylistener(keylistener l) void addmouselistener(mouselistener l) void removemouselistener(mouselistener l) void addmousemotionlistener(mousemotionlistener l) void removemousemotionlistener(mousemotionlistener l) void addtextlistener(textlistener l) void removetextlistener(textlistener l) void addwindowlistener(windowlistener l) void removewindowlistener(windowlistener l) [ 표13-27] 이벤트리스너를컴포넌트에추가또는제거할때사용하는메서드 Button,List, MenuItem, TextField Scrollbar Component Container Component Checkbox, CheckboxMen uitem, List, Choice Component Component Component TextField, TextArea Window void addwindowfocuslistener(windowfocuslistener l) void removewindowfocuslistener(windowfocuslistener l) Window void addwindowstatelistener(windowstatelistener l) void removewindowstatelistener(windowstatelistener l) Window

Chapter 13 AWT 와애플릿(Applet) 739 6.4 Adapter 클래스 이벤트핸들러를작성할때, 이벤트처리에필요한메서드의개수와는관계없이해당이 벤트리스너( 인터페이스) 에정의된모든추상메서드를구현해야한다는것은좀불편하다. 이러한불편한점을없애기위해서고안된것이 Adapter 클래스이며, 이벤트리스너를 직접구현하는대신에 면된다. Adapter 클래스를상속받아서원하는메서드만작성( 오버라이딩) 하 아래의코드는 KeyListener와 KeyAdapter 의경우를예로든것인데, 왼쪽의코드에서 는이벤트핸들러인 KeyHandler가이벤트리스너 KeyListener를구현했기때문에 KeyListener 에정의된세개의추상메서드를모두구현해야했지만, 오른쪽코드에서는 KeyListener를구현하는대신 하였다. KeyAdapter를상속받았기때문에원하는메서드만작성 class KeyHandler implements KeyListener { public void keypressed(keyevent e) { System.out.println(e.getKeyChar()); public void keyreleased(keyevent e) { public void keytyped(keyevent e) { class KeyHandler extends KeyAdapter { public void keypressed(keyevent e) { System.out.println(e.getKeyChar()); 이쯤에서이미눈치챘겠지만 아무내용도없이구현해놓았을뿐이다. Adapter클래스는그저이벤트리스너에정의된메서드를 interface KeyListener { public void keypressed(keyevent e); public void keyreleased(keyevent e); public void keytyped(keyevent e); class KeyAdapter implements KeyListener { public void keypressed(keyevent e) { public void keyreleased(keyevent e) { public void keytyped(keyevent e) { 이벤트핸들러를작성할때이벤트리스너를구현하는것과 것은코드를작성하기편리하다는것외에는차이가없다. Adapter클래스를상속받는 Adapter클래스 ComponentAdapter ContainerAdapter FocusAdapter KeyAdapter MouseAdapter MouseMotionAdapter WindowAdapter 이벤트리스너 (interface) ComponentListener ContainerListener FocusListener KeyListener MouseListener MouseMotionListener WindowListener [ 표13-28] Adapter클래스가구현한이벤트리스너

740 Java 의정석定石 [ 예제13-29]/ch13/TextFieldTest2.java import java.awt.*; import java.awt.event.*; class TextFieldTest2 extends Frame { Label lid; Label lpwd; TextField tfid; TextField tfpwd; Button ok; TextFieldTest2(String title) { super(title); // Frame(String title) 을호출한다. lid = new Label("ID :", Label.RIGHT); // Label의 text 정렬을오른쪽으로. lpwd = new Label("Password :", Label.RIGHT); // 약 10개의글자를입력할수있는 TextField 생성. tfid = new TextField(10); tfpwd = new TextField(10); tfpwd.setechochar('*'); // 입력한값대신 '*' 이보이게한다. ok = new Button("OK"); // OK버튼과 TextField에이벤트처리를위한 Listener 를추가해준다. tfid.addactionlistener(new EventHandler()); tfpwd.addactionlistener(new EventHandler()); ok.addactionlistener(new EventHandler()); setlayout(new FlowLayout()); // LayoutManager를 FlowLayout으로 add(lid); // 생성한 Component들을 Frame 에포함시킨다. add(tfid); add(lpwd); add(tfpwd); add(ok); setsize(450, 65); setvisible(true); // Frame 이화면에보이게한다. public static void main(string args[]) { TextFieldTest2 f = new TextFieldTest2("Login"); class EventHandler implements ActionListener { public void actionperformed(actionevent e){ String id = tfid.gettext(); // tfid에입력되어있는 text 를얻어온다. String password = tfpwd.gettext(); if (!id.equals("javachobo")){ System.out.println(" 입력하신 id 가유효하지않습니다. " + " 다시입력해주세요."); // id 를다시입력할수있도록, focus를 tfid 로옮긴다. tfid.requestfocus(); tfid.selectall(); // tfid에입력된 text 가선택되게한다. else if (!password.equals("asdf")) { System.out.println(" 입력하신비밀번호가틀렸습니다. " + " 다시입력해주시기바랍니다.");

Chapter 13 AWT 와애플릿(Applet) 741 // id를다시입력할수있도록 focus를 tfid 로옮긴다. tfpwd.requestfocus(); tfpwd.selectall(); else { System.out.println( id + " 님, 성공적으로로그인되었습니다."); // class EventHandler [ 실행결과] javachobo 님, 성공적으로로그인되었습니다. 위의예제는전에다루었던예제13-9 TextFieldTest.java에이벤트처리를추가한것이 다. 그외에도구조적인부분에서달라진부분이있는데, Frame을상속받는클래스를구 현하고 Frame 에포함되는컴포넌트들을인스턴스멤버로선언하고, Frame의생성자에서 컴포넌트를생성및설정하도록코드를작성하였다. 기존의코드보다더객체지향적으로 잘정리되어있다는것을느낄수있을것이다. 예제를실행한다음 ID와 Password를입력하고 OK 버튼을누르면, ID와 Password가 맞는지확인하고, 틀리면수정하라는메시지를사용자에게보낸다. tfid.addactionlistener(new EventHandler()); tfpwd.addactionlistener(new EventHandler()); ok.addactionlistener(new EventHandler()); OK버튼만아니라 ID와 Password를입력받는 TextField인 tfid,tfpwd에도 EventHandler 인스턴스를이벤트리스너로등록했다. 이렇게함으로써버튼을클릭할때만아니라 TextField에서 Enter키를눌렀을때도 ActionEvent 가처리되기때문에입력후에손을키보드에서마우스로옮기지않아도되 므로편리하다. 이제 ActionEvent 와같은고수준의이벤트가왜필요한지충분히이해가되었을것이다. requestfocus() - 원하는 Component가 focus 를갖도록할수있다. selectall() - TextField 또는 TextArea에입력된 text 전체를선택된상태로만든다. setechochar(char c) - 실제로입력된값을감추기위해화면에보여질문자를지정한다. 이외에도유용한메서드가많이있으니, Java API문서에서 TextField와 TextArea 그리 고그조상인 TextComponent 에대해서찾아보자. [ 참고] 원하는메서드를 TextField와 TextArea에서만찾아보는경우가많은데반드시 TextComponent도찾아봐야 한다.

742 Java의정석定石 2판 [ 예제13-30]/ch13/MouseEventTest.java import java.awt.*; import java.awt.event.*; class MouseEventTest extends Frame { Label location; MouseEventTest(String title) { super(title); // Frame(String title) 을호출한다. location = new Label("Mouse Pointer Location : "); location.setsize(195, 15); location.setlocation(5,30); location.setbackground(color.yellow); // Label 의배경색을노란색으로한다. add(location); // EventHandler의인스턴스를 Frame의 Listener 로등록한다. addmousemotionlistener(new EventHandler()); setsize(300, 200); setlayout(null); setvisible(true); public static void main(string args[]) { MouseEventTest mainwin = new MouseEventTest("MouseEventTest"); // main 메서드의끝 class EventHandler implements MouseMotionListener { public void mousedragged(mouseevent e) { public void mousemoved(mouseevent e) { location.settext("mouse Pointer Location : (" + e.getx() + ", " + e.gety()+ ")"); // EventHandler클래스의끝 [ 실행결과] 예제를실행시킨후, 마우스의포인터로 Frame 위를움직이면, 화면에포인터의좌표가 나타나게된다. 포인터의좌표를보여주기위해서 Label 을사용했다.

Chapter 13 AWT 와애플릿(Applet) 743 Frame 의위에서마우스의포인터를움직일때, MouseEvent가발생하며 MouseEvent의 mousemoved메서드가호출되며이벤트소스는 Frame이다. MouseEvent에는 getx() 와 gety() 가있는데, 이메서드들을이용하면, 마우스포인터의좌표를알수있다. [ 예제13-31]/ch13/TextComponentEventTest.java import java.awt.*; import java.awt.event.*; class TextComponentEventTest extends Frame { TextField tf; TextArea ta; TextComponentEventTest(String title) { super(title); // Frame(String title) 을호출한다. tf = new TextField(); ta = new TextArea(); add(ta, "Center"); add(tf, "South"); tf.addactionlistener(new ActionListener(){ public void actionperformed(actionevent e) { // TextField에서 Enter 를치면, tf에입력된 text를 TextArea 에추가한다. ta.append(tf.gettext() + "\n"); tf.settext(""); // tf의 text 를지운다. tf.requestfocus(); ); ta.seteditable(false); // TextArea의 text 를편집하지못하게한다. setsize(300, 200); setvisible(true); tf.requestfocus(); // focus가 TextField 에위치하도록한다. public static void main(string args[]) { TextComponentEventTest mainwin = new TextComponentEventTest("TextComponentEventTest"); // main 메서드의끝 [ 실행결과]

744 Java의정석定石 2판 위의예제는 TextField와 TextArea 를이용해서채팅창과같은화면을만든것이다. TextField에글자를입력하고 Enter 키를누르면, TextArea 에입력한글자들이나타난다. TextField에서 Enter 키를눌렀을때, ActionEvent의 actionperformed메서드가호출된 다는것을기억하고있을것이다. actionperformed메서드가호출되는 4가지경우를표 13-25 에서다시한번확인해보기바란다. TextArea 의내용을직접편집하지못하도록하기위해서, seteditable(false) 를사용했 다. 그래서실행시 TextArea의 text 를편집할수없으며, 바탕색이회색으로보이는것 이다. [ 참고] setcaretposition() 을이용하면 TextArea 내에서커서의위치를변경시킬수있다. [ 예제13-32]/ch13/CheckboxEventTest.java import java.awt.*; import java.awt.event.*; class CheckboxEventTest extends Frame { Label q1; Label q2; Label score; Checkbox q1cb1, q1cb2, q1cb3, q1cb4; Checkbox q2cb1, q2cb2, q2cb3, q2cb4; CheckboxGroup group; Button end; CheckboxEventTest(String title) { super(title); // Frame(String title) 을호출한다. setsize(500, 300); setlayout(new GridLayout(13,1)); q1 = new Label("1. 다음중 ActionEvent의 actionperformed 메서드가 " + " 호출되는경우는? ( 모두고르세요.)"); q1cb1 = new Checkbox("Button 을눌렀을때"); q1cb2 = new Checkbox("TextField에서 Enter 키를눌렀을때"); q1cb3 = new Checkbox("MenuItem 을클릭했을때"); q1cb4 = new Checkbox("List에서더블클릭으로 item 을선택했을때"); q2 = new Label("2. Frame의기본 LayoutManager 는? ( 하나만고르세요.)"); group = new CheckboxGroup(); q2cb1 = new Checkbox("FlowLayout", group, false); q2cb2 = new Checkbox("GridLayout", group, false); q2cb3 = new Checkbox("BorderLayout", group, false); q2cb4 = new Checkbox("CardLayout", group, false); score = new Label("* 결과 :"); end = new Button(" 이버튼을누르시면결과를알수있습니다."); end.addactionlistener(new ActionListener() { public void actionperformed(actionevent e) { float totalscore=0; if(q1cb1.getstate()) totalscore += 12.5; if(q1cb2.getstate()) totalscore += 12.5; if(q1cb3.getstate()) totalscore += 12.5; if(q1cb4.getstate()) totalscore += 12.5; if(q2cb3.getstate()) totalscore += 50; score.settext("* 결과 : 당신의점수는 " + totalscore + " 점입니다.");

Chapter 13 AWT 와애플릿(Applet) 745 ); add(q1); add(q1cb1); add(q1cb2); add(q1cb3); add(q1cb4); add(new Label("")); // 문제들사이에빈줄을하나삽입하기위해사용 add(q2); add(q2cb1); add(q2cb2); add(q2cb3); add(q2cb4); add(end); add(score); setvisible(true); public static void main(string args[]) { CheckboxEventTest mainwin = new CheckboxEventTest("CheckboxEventTest - Quiz"); // main 메서드의끝 [ 실행결과] Checkbox 를이용해서객관식문제를만드는예제이다. Checkbox의 getstate() 를이용해 서 Checkbox 의상태( 선택되었는지선택되지않았는지) 를알수있다. [ 예제13-33]/ch13/CheckboxEventTest2.java import java.awt.*; import java.awt.event.*; class CheckboxEventTest2 extends Frame { CheckboxGroup group; Checkbox cb1; Checkbox cb2; Checkbox cb3; CheckboxEventTest2(String title) { super(title);

746 Java 의정석定石 group = new CheckboxGroup(); cb1 = new Checkbox("red", group, true); cb2 = new Checkbox("green", group, false); cb3 = new Checkbox("blue", group, false); cb1.additemlistener(new EventHandler()); cb2.additemlistener(new EventHandler()); cb3.additemlistener(new EventHandler()); setlayout(new FlowLayout()); add(cb1); add(cb2); add(cb3); setbackground(color.red); setsize(300, 200); setvisible(true); public static void main(string args[]) { CheckboxEventTest2 mainwin = new CheckboxEventTest2("CheckboxEventTest2"); // main 메서드의끝 class EventHandler implements ItemListener { public void itemstatechanged(itemevent e) { Checkbox cb = (Checkbox)e.getSource(); String color = cb.getlabel(); if(color.equals("red")) { setbackground(color.red); else if (color.equals("green")) { setbackground(color.green); else { setbackground(color.blue); // class EventHandler [ 실행결과]

Chapter 13 AWT 와애플릿(Applet) 747 예제를실행시킨후 Checkbox(radio button) 중의하나를클릭하면, Frame의배경색 (background color) 이변경될것이다. 이때, 이벤트소스는클릭한 Checkbox 이고, ItemEvent 가발생하며, itemstatechanged 메서드가호출되어진다. itemstatechanged메 서드내에서 getsource() 를호출하면이벤트소스를얻을수있다. getsource() 는모든 이벤트클래스의조상인 에서사용할수있는유용한메서드이다. EventObject클래스에정의되어있는것으로모든이벤트클래스 public void itemstatechanged(itemevent e) { Checkbox cb = (Checkbox)e.getSource();... [ 예제13-34]/ch13/CardLayoutEventTest.java import java.awt.*; import java.awt.event.*; class CardLayoutEventTest extends Frame { Button first, prev, next, last; Panel buttons; Panel slide; Panel card1, card2, card3, card4, card5; // slide에포함될 Panel들 CardLayout card; CardLayoutEventTest(String title) { super(title); // 조상인 Frame의생성자 Frame(String title) 을호출 // 화면을담을 Panel 을담는다. slide = new Panel(); card = new CardLayout(); slide.setlayout(card); // 버튼을담을 Panel 을만든다. buttons = new Panel(); buttons.setlayout(new FlowLayout()); first = new Button("<<"); prev = new Button("<"); next = new Button(">"); last = new Button(">>"); buttons.add(first); buttons.add(prev); buttons.add(next); buttons.add(last); // 버튼에이벤트리스너를추가한다. first.addactionlistener(new ActionListener(){ public void actionperformed(actionevent e) { // CardLayout의첫번째 slide(panel) 이보이도록한다. card.first(slide); ); prev.addactionlistener(new ActionListener(){ public void actionperformed(actionevent e) { // 현재 slide의이전 slide(panel) 이보이도록한다.

748 Java의정석定石 2판 card.previous(slide); ); next.addactionlistener(new ActionListener(){ public void actionperformed(actionevent e) { // 현재 slide의다음 slide(panel) 이보이도록한다. card.next(slide); ); last.addactionlistener(new ActionListener(){ public void actionperformed(actionevent e) { // CardLayout의마지막 slide(panel) 이보이도록한다. card.last(slide); ); card1= new Panel(); card1.setbackground(color.gray); card1.add(new Label(" 첫번째페이지입니다.")); card2= new Panel(); card2.add(new Label(" 두번째페이지입니다.")); card2.setbackground(color.orange); card3= new Panel(); card3.add(new Label(" 세번째페이지입니다.")); card3.setbackground(color.blue); card4= new Panel(); card4.add(new Label(" 네번째페이지입니다.")); card4.setbackground(color.cyan); card5= new Panel(); card5.add(new Label(" 다섯번째페이지입니다.")); card5.setbackground(color.pink); // slide(panel) 에 card1(panel) 을 "1" 이란이름으로추가한다. slide.add(card1, "1"); slide.add(card2, "2"); slide.add(card3, "3"); slide.add(card4, "4"); slide.add(card5, "5"); add("south", buttons); add("center", slide); setsize(200, 200); setlocation(200, 200); setvisible(true); card.show(slide,"1"); // 첫번째슬라이드(card1) 가나타나게한다. public static void main(string args[]) { CardLayoutEventTest mainwin = new CardLayoutEventTest("CardLayoutTest");

Chapter 13 AWT 와애플릿(Applet) 749 [ 실행결과] CardLayout을이용해서 5개의 Panel을슬라이드형식으로화면에보여주는예제이다. 버 튼을통해각화면(Panel) 으로이동할수있다. Frame의 Center에 CardLayout이레이아웃매니저인 slide 를넣고, South에는버튼이 담긴 Panel 을넣었다. 또다시 slide에 5개의 Panel이추가되고버튼에의해 5개의 Panel중어떤것이보일것 인지가달라진다. [ 예제13-35]/ch13/TextEditor.java import java.awt.*; import java.awt.event.*; import java.io.*; class TextEditor extends Frame { String filename; TextArea content; MenuBar mb; Menu mfile; MenuItem minew, miopen, misaveas, miexit; TextEditor(String title) { super(title); content = new TextArea(); add(content); mb = new MenuBar(); mfile = new Menu("File"); minew = new MenuItem("New"); miopen = new MenuItem("Open"); misaveas = new MenuItem("Save As..."); miexit = new MenuItem("Exit"); mfile.add(minew); mfile.add(miopen); mfile.add(misaveas); mfile.addseparator(); // 메뉴분리선(separator) 을넣는다. mfile.add(miexit); mb.add(mfile); // MenuBar에 Menu 를추가한다. setmenubar(mb); // Frame에 MenuBar 를포함시킨다.

750 Java 의정석定石 // 메뉴에이벤트핸들러를등록한다. MyHandler handler = new MyHandler(); minew.addactionlistener(handler); miopen.addactionlistener(handler); misaveas.addactionlistener(handler); miexit.addactionlistener(handler); setsize(300, 200); setvisible(true); // 선택된파일의내용을읽어서 TextArea에보여주는메서드 void fileopen(string filename) { FileReader fr; BufferedReader br; StringWriter sw; try { fr = new FileReader(fileName); br= new BufferedReader(fr); sw = new StringWriter(); int ch = 0; while ((ch=br.read())!=-1) { sw.write(ch); br.close(); content.settext(sw.tostring()); catch(ioexception e) { e.printstacktrace(); // fileopen 메서드의끝 // TextArea 의내용을지정된파일에저장하는메서드 void saveas(string filename) { FileWriter fw; BufferedWriter bw; try { fw = new FileWriter(fileName); bw= new BufferedWriter(fw); bw.write(content.gettext()); // TextArea 의내용을파일에저장한다. bw.close(); catch (IOException ie) { ie.printstacktrace(); // try // saveas메서드의끝 public static void main(string args[]) { TextEditor mainwin = new TextEditor("Text Editor"); // main 메서드의끝 // 메뉴를클릭했을때메뉴별처리코드 class MyHandler implements ActionListener { public void actionperformed(actionevent e) {

Chapter 13 AWT 와애플릿(Applet) 751 String command = e.getactioncommand(); if(command.equals("new")) { content.settext(""); else if(command.equals("open")) { FileDialog fileopen = new FileDialog(TextEditor.this, " 파일열기"); fileopen.setvisible(true); filename = fileopen.getdirectory() + fileopen.getfile(); System.out.println(fileName); // 선택된파일의내용을 TextArea 에보여준다. fileopen(filename); else if(command.equals("save As...")) { FileDialog filesave = new FileDialog(TextEditor.this," 파일저장",FileDialog.SAVE); filesave.setvisible(true); filename = filesave.getdirectory() + filesave.getfile(); System.out.println(fileName); // 현재 TextArea 의내용을선택된파일에저장한다. saveas(filename); else if(command.equals("exit")) { System.exit(0); // 프로그램을종료시킨다. // class MyHandler // TextEditor클래스의끝 [ 실행결과] 이예제는 FileDialog와 TextArea를이용해서파일편집기를만든것인데, 예제가복잡해지는것을피하기위해기능을최소화했다. FileDialog의사용법과메뉴의이벤트처리등을눈여겨보자. 파일을읽고, 저장하는부분은후에배우게될것이므로지금은이부분을제외한나머지부분만이해해도좋다. [ 참고] 이예제에서보완되어야할부분을생각해보고, 기능을하나둘씩추가해가는것도실력향상에많은도움이될것이다.

752 Java 의정석定石 [ 예제13-36]/ch13/PaintFrameTest.java import java.awt.*; import java.awt.event.*; class PaintFrameTest { public static void main(string args[]) { PaintFrame f = new PaintFrame("PaintFrame"); Graphics g = f.getgraphics(); g.setcolor(color.red); for(int i=0; true ; i+=f.speed) { try { Thread.sleep(100); // 0.1 초동안실행을지연시킨다. catch (InterruptedException e) { g.clearrect(0,0,300,300); g.drawstring("hello", i, 150); i = (i<300)? i : 0; // main메서드의끝 class PaintFrame extends Frame { int speed = 1; Scrollbar sb = new Scrollbar(Scrollbar.HORIZONTAL, 0, 5, 0, 50); Label lspeed = new Label("Speed : 1"); PaintFrame(String title) { super(title); lspeed.setbackground(color.yellow); lspeed.setsize(65, 15); lspeed.setlocation(10, 30); sb.setsize(260, 20); sb.setlocation(20, 250); add(sb); add(lspeed); sb.addadjustmentlistener(new MyHandler()); addwindowlistener(new MyHandler()); setsize(300, 300); setlayout(null); setvisible(true); setresizable(false); // Frame 의크기를변경할수없도록한다. class MyHandler extends WindowAdapter implements AdjustmentListener { public void adjustmentvaluechanged(adjustmentevent e){ speed = sb.getvalue(); // Scrollbar 의현재값을얻는다. lspeed.settext("speed : " + speed); public void windowclosing(windowevent we) { System.exit(0); // class PaintFrame

Chapter 13 AWT 와애플릿(Applet) 753 [ 실행결과] 이예제를시작하면화면가운데왼쪽에서오른쪽으로글자 (Hello) 가이동한다. 아래쪽의 Scrollbar 를움직이면, 이글자가움직이는속도에변화를줄수있다. 마우스를이용하지 않고화살표키를눌러서 [ 예제13-37]/ch13/ChatWin.java import java.awt.*; import java.awt.event.*; class ChatWin extends Frame { String nickname = ""; TextArea ta = new TextArea(); Scrollbar 를움직일수도있다. Panel p = new Panel(); TextField tf = new TextField(); ChatWin() { this("guest"); ChatWin(String nickname) { super("chatting"); this.nickname = nickname; setbounds(100, 100, 300, 200); p.setlayout(new BorderLayout()); p.add(tf, "Center"); add(ta, "Center"); add(p, "South"); addwindowlistener(new WindowAdapter(){ public void windowclosing(windowevent e) { System.exit(0); );

754 Java의정석定石 2판 EventHandler handler = new EventHandler(); ta.addfocuslistener(handler); tf.addfocuslistener(handler); tf.addactionlistener(handler); ta.settext("#" + nickname + " 님즐거운채팅되세요."); ta.seteditable(false); setvisible(true); tf.requestfocus(); public static void main(string[] args) { if(args.length!= 1) { System.out.println("USAGE : java ChatWin NICKNAME"); System.exit(0); new ChatWin(args[0]); // main class EventHandler extends FocusAdapter implements ActionListener { public void actionperformed(actionevent ae) { String msg = tf.gettext(); if("".equals(msg)) return; ta.append("\r\n" + nickname +">"+ msg); tf.settext(""); public void focusgained(focusevent e) { tf.requestfocus(); // class EventHandler // class [ 실행결과] C:\jdk1.5\work\ch13>java ChatWin 자바맨 이예제는채팅프로그램에사용되는채팅창을간단하게만들어본것이다. TextField에서 Enter키를누르면 ActionEvent가발생하고입력한내용이채팅창인 TextArea에나타난 다.

Chapter 13 AWT 와애플릿(Applet) 755 class FocusHandler extends FocusAdapter { public void focusgained(focusevent e) { tf.requestfocus(); // TextField 가포커스를잃으면다시포커스를얻게한다. 그외에 를클릭해서 FocusEvent에대한이벤트처리도하였는데그이유는채팅창의다른컴포넌트 TextField가포커스를잃더라도다시포커스를 TextField로이동시켜서사 용자가입력을편하게하도록하기위해서이다. 아래의예제는 Frame 에여러종류의컴포넌트를추가하고, 가능한모든종류의 Listener 를구현한하나의이벤트처리클래스를각컴포넌트의 Listener 로등록한다. 사용자의동작에의해발생한이벤트의메서드는, 자신의이름과이벤트소스와관련정 보를화면(System.out) 에출력한다. [ 예제13-38]/ch13/EventTest.java // 소스는생략합니다. java_jungsuk_src.zip 에서찾을수있습니다. // java_jungsuk_src.zip는 http://www.javachobo.com 에서다운로드받으실수있습니다. [ 실행결과] C:\jdk1.5\work\ch13>java EventTest [1] componentresized - java.awt.frame[frame0,200,200,500x319,hidden,layout=java.awt.flowlayout,resizable,tit le=event Test] [2] componentresized - java.awt.frame[frame0,200,200,500x319,hidden,layout=java.awt.flowlayout,resizable,tit le=event Test] [3] componentresized - java.awt.button[button0,8,67,49x23,label=button] [4] componentresized - java.awt.checkbox[checkbox0,62,67,66x23,label=option,state=false] [5] componentresized - java.awt.panel[panel0,248,74,10x10,layout=java.awt.flowlayout]

756 Java의정석定石 2판 [6] componentresized - java.awt.label[label0,263,67,45x23,align=left,text=label] [7] componentresized - java.awt.list[list0,313,47,124x64,selected=null]... 출력된결과를통해서어떤동작을했을때어떤이벤트의메서드가가발생하는지자세 히알수있을것이다. 하나의동작에도여러분들이생각했던것보다많은메서드들이호출된다는것을알수 있을것이다. 예를들면, TestArea 에글자하나를입력했을때, keypressed(), keyreleased(), keytyped() 모두 3 개의메서드가순서대로호출된다. 여기서중요한것은호출되는메서드들의종류와순서, 그리고이벤트소스이다. 각 Component 에여러가지동작을함으로써다양한이벤트가발생하도록하고그결과를 확인하도록한다. 아래에는여러분들이직접해보면좋을테스트를몇가지적어보았다. 실행해보고그결과를확인하라. [ 참고] 이벤트는마우스또는키보드를통한사용자의동작뿐만아니라프로그램코드에의해서도발생할수있다는사실을확인하자. [ 참고] 마우스를움직일때마다호출되는 MouseMoved메서드때문에이벤트발생으로인해호출되는메서드를구분하기어렵다면, MouseMoved 메서드의내용을주석처리하자. 1. 키보드의키하나를계속누르고있을때어떤일이생기는지확인하라. 2. Ctrl과 Alt 같은특수키를눌렀을때와일반키를눌렀을때를비교하라. 3. TextField에서 Enter키를눌렀을때 4. Tab키를눌러서 focus를이동했을때 5. 마우스의포인터를 Frame에서 Canvas 의영역안으로이동했을때( 그리고, 그반대로) 6. List에있는 item하나를선택해서더블클릭했을때 7. Choice에서다른 item을선택했을때 8. Frame 의크기를변경했을때 아래의예제는모든종류의 Listener 를구현한클래스이다. 이예제를만든이유는이벤트처리를위한 Event Handler 를작성하는데도움을주기위해서이다. Listener Adapter 클래스를사용하지못하는경우라면, Listener Interface에정의된모든메서드들을구현해야하므로단순반복적인코딩을해야하고, 오타로인한에러가발생하기쉽다. 이예제파일을에디터로열어서필요한부분을복사해서붙이는식으로하면코딩이보다쉽고정확해질것이다. [ 예제13-39]/ch13/AllEventHandler.java import java.awt.event.*; class AllEventHandler implements ActionListener, ComponentListener, MouseMotionListener, MouseListener, MouseWheelListener, KeyListener, TextListener, FocusListener, ItemListener, AdjustmentListener, WindowListener, WindowFocusListener, WindowStateListener, ContainerListener { // ActionListener의메서드 public void actionperformed(actionevent ae) { // ComponentListener 의메서드 public void componentmoved(componentevent ce) { public void componenthidden(componentevent ce) {

Chapter 13 AWT 와애플릿(Applet) 757 public void componentresized(componentevent ce) { public void componentshown(componentevent ce) { // MouseMotionListener 의메서드 public void mousedragged(mouseevent me) { public void mousemoved(mouseevent me) { // MouseListener 의메서드 public void mousepressed(mouseevent me) { public void mousereleased(mouseevent me) { public void mouseentered(mouseevent me) { public void mouseexited(mouseevent me) { public void mouseclicked(mouseevent me) { // MouseWheelListener 의메서드 public void mousewheelmoved(mousewheelevent e) { // KeyListener 의메서드 public void keypressed(keyevent ke) { public void keyreleased(keyevent ke) { public void keytyped(keyevent ke) { // TextListener 의메서드 public void textvaluechanged(textevent te) { // FocusListener 의메서드 public void focusgained(focusevent fe) { public void focuslost(focusevent fe) { // ItemListener 의메서드 public void itemstatechanged(itemevent ie) { // AdjustmentListener 의메서드 public void adjustmentvaluechanged(adjustmentevent ae) { // WindowListener 의메서드 public void windowclosing(windowevent we) { public void windowopened(windowevent we) { public void windowiconified(windowevent we) { public void windowdeiconified(windowevent we) { public void windowclosed(windowevent we) { public void windowactivated(windowevent we) { public void windowdeactivated(windowevent we) { // WindowFocusListener 의메서드 public void windowgainedfocus(windowevent e) { public void windowlostfocus(windowevent e) { // WindowStateListener 의메서드 public void windowstatechanged(windowevent e) { // ContainerListener 의메서드 public void componentadded(containerevent ce) { public void componentremoved(containerevent ce) { // End of EventHandler class

758 Java의정석定石 2판 7. AWT 의그래픽 이제 AWT 를이용해서그림을그리는방법에대해서알아볼차례이다. 이단원에서는 AWT 에서선과도형을어떻게그리고어떤과정을통해서그려지는지에대해서배울것이며, 이 단원을마치고나면간단한그림판정도는만들수있을것이다. 여기서는 AWT 그래픽의기본적인내용만을다루기때문에자바를이용해서이미지처리나 게임과같이높은수준의그래픽기능을요구하는어플리케이션을작성하는데부적합하다는 오해를할지도모르겠다. 그러나자바에서는오래전부터향상된그래픽처리를위한 API인 Java2D 를제공해왔는데. Java2D는포토샵으로유명한 Adobe 사와자바를탄생시킨썬(SUN) 사가공동제작한것으로 이미지프로세싱이나렌더링과같은고수준의그래픽처리에필요한모든것을제공하는강력 한가능의 API 이다. 백문이불여일견이니 Java2D데모프로그램을실행해서 Java2D로어떤 일들을할수있는지직접확인해보자. [ 그림13-12] Java2Demo.jar의실행화면 [ 참고] Java2D 데모프로그램은 JDK 설치디렉토리\demo\jfc\Java2D 에있으며 Java2Demo.html를웹브라우저로 열던가, 콘솔에서 java -jar Java2Demo.jar와같이입력하여Java2Demo.jar 를실행시키면볼수있다. [ 참고] Java2D는 JDK API의일부로 java.awt 패키지와그하위패키지에포함되어있다.

Chapter 13 AWT 와애플릿(Applet) 759 AWT는자바초기에작성되었기때문에 JDK의버전이올라감에따라보다높은기능의 API 가필요했다. 그래서 Java2에서부터 JFC(Java Foundation Classes) 라는이름으로 Swing과 Java2D 가추가로제공되었다. Swing은 AWT보다향상된 UI(User interface) 를제공하였고, Java2D는 AWT 보다향상된그래픽기능을제공하였다. 그럼에도불구하고 AWT를배워야하는이유는 AWT가 Swing과 Java2D의뿌리이기때문이 다. Swing이나 Java2D 가흥미롭고매력적인분야이기는하나, 특히국내에서는자바가주로웹 프로그래밍이나서버프로그래밍에사용되기때문에 Swing이나 Java2D를자바의기본내용 에포함시키는것보다는이들의뿌리인 생각했다. AWT의핵심내용만을포함시키는것이더낫다고 7.1 paint() 와 Graphics paint() 는컴포넌트에그림을그리기위한것으로 Component클래스에정의되어있어서모 든컴포넌트에서사용할수있다. 그림을그리고자하는컴포넌트, 주로 Frame, Canvas, Panel 등의 paint() 를알맞게오버라이딩하면된다. paint() 의선언부는다음과같이 Graphics 를매개변수로정의하고있으며, paint() 를작성할 때는 Graphics 가가지고있는다양한그래픽메서드를이용해서그림을그리게된다. public void paint(graphics g) {... 모든컴포넌트는 Graphics 객체를가지고있으며, Graphics객체에는각컴포넌트의그래픽 관련된정보가담겨져있다. 그래서컴포넌트에그림을그리고자할때는 getgraphics() 를호 출해서컴포넌트의 Grapphics 객체에대한참조를먼저얻어낸다음, Graphics객체가가지고 있는다양한그래픽메서드를이용해서작업하면된다. 예를들어 Panel에선을그리고자한 다면다음과같이할수있다. Panel p = new Panel(); Graphics g = p.getgraphics(); g.drawline(0,0, 10, 10); //Panel 에두점 (0,0) 과 (10,10) 을잇는선을그린다. [ 참고] 여기서말하는 Graphics객체라는것은추상클래스인 Graphics 를완전히구현한클래스의객체를말한다. Graphics 가제공하는주요메서드는다음과같다.

760 Java의정석定石 2판 1. 문자출력관련된메서드 - 문자열을출력할수있으며, 출력할문자열의폰트(font) 를지정할수있다. FontMetrics 객체는지정된폰트에대한상세한정보를제공한다. void drawstring(string str, int x, int y) - (x, y) 위치에문자열을출력한다. Font getfont() - 현재설정되어있는 Font 를얻는다. void setfont(font font) - 출력할문자열의폰트를지정한다. FontMetrics getfontmetrics() - FontMetrics 객체를반환한다. 2. 색과관련된메서드 - 출력할그림의색을지정하거나지정된색의정보를얻을수있다. Color getcolor() - 현재설정되어있는 Color 를얻는다. void setcolor(color c) - 출력할색을지정한다. 3. 도형과관련된메서드 - 다양한도형을그리는메서드. draw 로시작하는것은도형의선만그리고, fill 로시작하는것은도형의내부를선의색으로채운다. - 선을그리는메서드 void drawline(int x1, int y1, int x2, int y2) - 타원을그리는메서드 void drawoval(int x, int y, int width, int height) void filloval(int x, int y, int width, int height) - 사각형을그리는메서드 void drawrect(int x, int y, int width, int height) void fillrect(int x, int y, int width, int height) - 둥근사각형을그리는메서드 void drawroundrect(int x, int y, int width, int height, int arcwidth, int archeight) void fillroundrect(int x, int y, int width, int height, int arcwidth, int archeight) - 입체사각형을그리는메서드 void draw3drect(int x, int y, int width, int height, boolean raised) void fill3drect(int x, int y, int width, int height, boolean raised) - 호를그리는메서드 void drawarc(int x, int y, int width, int height, int startangle, int arcangle) void fillarc(int x, int y, int width, int height, int startangle, int arcangle) - 다각형을그리는메서드 void drawpolygon(int[] xpoints, int[] ypoints, int npoints) void fillpolygon(int[] xpoints, int[] ypoints, int npoints) void drawpolyline(int[] xpoints, int[] ypoints, int npoints) 4. 기타 void clearrect(int x, int y, int width, int height) - 지정된영역을지운다. boolean drawimage(image img, int x, int y, ImageObserver observer) 미지를그린다. - (x,y) 의위치에이 다음은 Graphics가제공하는다양한메서드를이용해서 Frame 에그림을그리는예제이다. [ 예제13-40]/ch13/GraphicsEx1.java import java.awt.*; import java.awt.event.*; class GraphicsEx1 extends Frame { public static void main(string[] args) {

Chapter 13 AWT 와애플릿(Applet) 761 new GraphicsEx1("GraphicsEx1"); public void paint(graphics g) { g.setfont(new Font("Serif", Font.PLAIN, 15)); g.drawstring("graphics 를이용해서그림을그립니다.",10, 50); g.drawoval(50,100, 50,50); g.setcolor(color.blue); g.filloval(100,100, 50,50); g.setcolor(color.red); g.drawline(100,100, 150,150); g.fillroundrect(200, 100, 120, 80, 30, 30); g.setcolor(color.orange); g.fillpolygon(new int[]{ 50, 100, 150, 200, new int[]{250, 200, 200, 250, 4); g.setcolor(color.cyan); g.fillarc(250, 200, 100, 100, 0, 120); public GraphicsEx1(String title) { super(title); addwindowlistener( new WindowAdapter() { public void windowclosing(windowevent we) { System.exit(0); ); // Frame 을 (100,100) 의위치에 width 400, height 300 크기로보이게한다. setbounds(100,100, 400,300); setvisible(true); // class [ 실행결과]

762 Java의정석定石 2판 7.2 AWT쓰레드와 repaint() 바로전예제에서 paint() 를오버라이딩했다는것은알겠는데호출하는부분이없는데어떻 게그림이그려졌을까? 라는의문이들었을것이다. 그것은바로 paint() 는우리가직접호출하지않아도 AWT쓰레드에의해서자동적으로호출 되기때문이다. AWT쓰레드는 GUI어플리케이션을실행하면자동적으로생성되는데몬쓰레드로평소에는 대기상태에있다가화면이갱신되어야할상황이발생되면, paint() 또는 update() 를호출해서 화면이다시그려지도록한다. AWT 쓰레드에의해자동적으로화면이갱신되는상황은다음과같다. 처음화면에나타날때 다른화면에가려져있던부분이다시화면에나타날때 아이콘화되어있다가원래크기로화면에나타날때 위의상황이외에도화면이다시그려지도록하려면 repaint() 를호출하면된다. repaint() 는 AWT 쓰레드에게화면을다시그릴것을요청한다. AWT쓰레드는 update() 를호출하고 update() 는다시 paint() 를호출한다. repaint() - AWT 쓰레드에게화면을갱신할것을요청한다. AWT쓰레드는 0.1초마다확인해서요청이있으면 update() 를호출한다. update(graphics g) - 화면을지우고 paint(graphics g) 를호출한다. repaint() update(graphics g) paint(graphics g) [ 그림13-13] repaint() 에의해호출되는메서드 [ 예제13-41]/ch13/GrapihcsEx2.java import java.awt.*; import java.awt.event.*; class GraphicsEx2 extends Frame implements MouseMotionListener { int x = 0; int y = 0; public static void main(string[] args) { new GraphicsEx2("GraphicsEx2"); public GraphicsEx2(String title) { super(title); addmousemotionlistener(this); addwindowlistener( new WindowAdapter() { public void windowclosing(windowevent we) {

Chapter 13 AWT 와애플릿(Applet) 763 ); System.exit(0); // Frame 을 (100, 100) 의위치에 width 500, height 500 크기로보이게한다. setbounds(100,100, 500,500); setvisible(true); public void paint(graphics g) { g.drawstring(" 마우스를움직여보세요.",10, 50); g.drawstring("*", x, y); public void mousemoved(mouseevent me) { x = me.getx(); y = me.gety(); repaint(); public void mousedragged(mouseevent me) { // class [ 실행결과] 높이와폭이 500픽셀인 Frame 을생성하고, 마우스포인터의위치에 * 을출력하는예제이 다. Frame 영역내에서마우스포인터를이동시키면 * 도따라움직이게된다. public void mousemoved(mouseevent me) { x = me.getx(); y = me.gety(); repaint();

764 Java의정석定石 2판 마우스를움직이면 MouseEvent가발생하고이벤트핸들러의 mousemoved() 가호출된다. MouseEvent의 getx(), gety() 를통해포인터의위치를얻어서멤버변수 x, y 에저장한다. 그리고 repaint() 를호출해서 Frame 을화면에다시그리도록해야새로운위치에 * 이출력 된다. 만일 repaint() 를호출하지않으면마우스를움직여도 * 이이동하지않는다. repaint() 를주 석처리해서컴파일하고실행한다음그결과를직접확인해보자. [ 예제13-42]/ch13/GrapihcsEx3.java import java.awt.*; import java.awt.event.*; class GraphicsEx3 extends Frame implements MouseMotionListener { int x = 0; int y = 0; public static void main(string[] args) { new GraphicsEx3("GraphicsEx3"); public GraphicsEx3(String title) { super(title); addmousemotionlistener(this); addwindowlistener( new WindowAdapter() { public void windowclosing(windowevent we) { System.exit(0); ); // Frame 을 (100, 100) 의위치에 width 500, height 500 크기로보이게한다. setbounds(100,100, 500,500); setvisible(true); public void paint(graphics g) { g.drawstring(" 마우스를움직여보세요.",10, 50); g.drawstring("*", x, y); public void update(graphics g) { paint(g); public void mousemoved(mouseevent me) { x = me.getx(); y = me.gety(); repaint(); public void mousedragged(mouseevent me) { // class

Chapter 13 AWT 와애플릿(Applet) 765 [ 실행결과] 전에설명한것과같이 update() 는컴포넌트의영역을지우고배경색으로채우고 paint() 를호출한 다. 그러나이예제에서는아래와같이 update() 가컴포넌트영역을지우지않고 paint() 만호 출하도록오버라이딩하였다. public void update(graphics g) { paint(g); 이렇게하면이전예제와는달리마우스포인터의자취가남게된다. 이번엔윈도우에서 'Alt+tab' 키를눌러서 Frame이다른화면에가려지게했다가다시 'Alt+tab' 키를눌러서다시화면에나타나게해보자. Frame이다른화면에의해가려졌다가다시나타나는경우에는자동적으로 Frame영역을완 전히새로그리기때문에포인터의자취가사라지게된다. 그래도이과정에서 paint() 는호출 되기때문에 paint() 에서그린부분은 Frame 에다시그려진다. public void paint(graphics g) { g.drawstring(" 마우스를움직여보세요.",10, 50); g.drawstring("*", x, y); 화면이가려졌다가나타나도지워지지않게하는방법은바로다음단원에서배울것이다.

766 Java의정석定石 2판 7.3 Image 를이용해서이미지출력하기 Image클래스는 gif, jpg 와같은형식의이미지파일을보여주거나가상화면(off-screen) 을생성하는데사용된다. 예를들어 getjava.gif라는파일을보여주려면다음과같은코드를사용하면된다. Toolkit tk = Toolkit.getDefaultToolkit(); Image img = tk.getimage("getjava.gif"); g.drawimage(img, 0, 0, this); drawimage(image img, int x, int y, ImageObserver obj) 는 Graphics가제공하는것으로 이미지(img) 를지정된위치(x, y) 에출력한다. 이미지가로딩되는데시간이걸리기때문에로 딩이진행되는상태에따라화면에다시그려줘야할필요가있다. 그래서이미지가로딩되고 있는상태를알려줄대상을 ImageObserver 로지정해야한다. 모든 AWT컴포넌트는 ImageObserver인터페이스를구현했기때문에 ImageObserver로컴 포넌트자신(this) 을지정하는것이보통이다. [ 그림13-14] Java API문서에서 Component를검색한화면 보통실제화면에직접그림을그리는대신가상화면에그림을그린다음에실제화면으로복 사하는경우가많다. 실제화면에직접그림을그리면깜빡거림이생기기도하고, 이전예제에 서처럼실행시에그린그림이보존되지않기때문이다. 다음은코드는 createimage() 를이용해서폭이 500, 높이가 500인 Image객체를생성한다 음 getgraphics() 를통해 Image객체의 Graphics 객체를얻어서문자열을출력한다. 모든그래픽작업을마친다음에는 제화면으로복사한다. drawimage() 를이용해서가상화면에그려진그림을실 Image img = createimage(500, 500); Graphics gimg= img.getgraphics(); gimg.drawstring(" 왼쪽버튼을누른채로마우스를움직여보세요.",10, 50); //... g.drawimage(img,0,0,this); // 가상화면에그려진그림을복사한다.

Chapter 13 AWT 와애플릿(Applet) 767 다음예제는이전예제를가상화면을사용하도록변경한것으로실행시에마우스로그린그 림이다른화면에가려졌다가다시나타나도지워지지않는다. [ 예제13-43]/ch13/GrapihcsEx4.java import java.awt.*; import java.awt.event.*; class GraphicsEx4 extends Frame implements MouseMotionListener { int x = 0; int y = 0; Image img = null; Graphics gimg = null; public static void main(string[] args) { new GraphicsEx4("GraphicsEx4"); public GraphicsEx4(String title) { super(title); addmousemotionlistener(this); addwindowlistener( new WindowAdapter() { public void windowclosing(windowevent we) { System.exit(0); ); // Frame 을 (100, 100) 의위치에 width 500, height 500 크기로보이게한다. setbounds(100,100, 500,500); setvisible(true); img = createimage(500, 500); gimg = img.getgraphics(); gimg.drawstring(" 왼쪽버튼을누른채로마우스를움직여보세요.",10, 50); repaint(); public void paint(graphics g) { if(img!=null) g.drawimage(img,0,0,this); // 가상화면에그려진그림을 Frame에복사 public void mousemoved(mouseevent me) { public void mousedragged(mouseevent me) { if (me.getmodifiersex()==mouseevent.button1_down_mask ) { x = me.getx(); y = me.gety(); gimg.drawstring("*", x, y); repaint(); // class

768 Java의정석定石 2판 [ 실행결과] Image와 Image의 Graphics 를멤버변수로정의하고, 생성자에서 createimage() 를통해서 Frame과같은크기의 Image 를생성하고, 생성된 Image에서 getgraphics() 를호출하여 Image에대한 Graphics 를얻는다. 이렇게해서얻어진 Graphics에 drawstring() 과같은메 서드를호출해서작업한내용은 Image 에그려지게된다. Image img = null; Graphics gimg = null; public GraphicsEx4(String title) {... img = createimage(500, 500); gimg = img.getgraphics(); gimg.drawstring(" 왼쪽버튼을누른채로마우스를움직여보세요.",10, 50); paint() 에서는단순히가상화면(img) 에그려진내용을 Frame 에복사하기만하면된다. public void paint(graphics g) { if(img!=null) g.drawimage(img,0,0,this); // 가상화면에그려진그림을 Frame에복사 이전예제와는달리왼쪽버튼을누른상태로포인터를이동했을때만그림이그려지도록하 기위해 mousedragged() 를구현하였다.

Chapter 13 AWT 와애플릿(Applet) 769 public void mousedragged(mouseevent me) { if (me.getmodifiersex()==mouseevent.button1_down_mask ) { x = me.getx(); y = me.gety(); gimg.drawstring("*", x, y); repaint(); 드래깅할때 Ctrl 키가눌러졌는지확인하려면다음과같이.BUTTON1_DOWN_MASK와 CTRL_DOWN_MASK 를더해주면된다. if(me.getmodifiersex()==mouseevent.button1_down_mask+ MouseEvent.CTRL_DOWN_MASK) [ 예제13-44]/ch13/GrapihcsEx5.java import java.awt.*; import java.awt.event.*; class GraphicsEx5 extends Frame implements MouseMotionListener { int x = 0; int y = 0; Image img = null; Graphics gimg = null; public static void main(string[] args) { new GraphicsEx5("GraphicsEx5"); public GraphicsEx5(String title) { super(title); addmousemotionlistener(this); addwindowlistener( new WindowAdapter() { public void windowclosing(windowevent we) { System.exit(0); ); // Frame 을 (100, 100) 의위치에 width 500, height 500 크기로보이게한다. setbounds(100,100, 500,500); setvisible(true); img = createimage(500, 500); gimg = img.getgraphics(); gimg.drawstring(" 왼쪽버튼을누른채로마우스를움직여보세요.",10, 50); repaint();

770 Java의정석定石 2판 public void paint(graphics g) { if(img==null) return; g.drawimage(img,0,0,this); // 가상화면에그려진그림을 Frame에복사 public void mousemoved(mouseevent me) { x = me.getx(); y = me.gety(); public void mousedragged(mouseevent me) { if (me.getmodifiersex()!=mouseevent.button1_down_mask ) return; gimg.drawline(x,y, me.getx(),me.gety()); x = me.getx(); y = me.gety(); repaint(); // class [ 실행결과] 전의예제에서 drawstring() 대신 drawline() 을사용해서 Frame에자유롭게선을그릴수있 도록하였다. 이전예제와비교해보고어떤차이가있는지확인해보자. [ 예제13-45]/ch13/GrapihcsEx6.java import java.awt.*; import java.awt.event.*; class GraphicsEx6 extends Frame { Image img = null;

Chapter 13 AWT 와애플릿(Applet) 771 public GraphicsEx6(String title) { super(title); addwindowlistener( new WindowAdapter() { public void windowclosing(windowevent we) { System.exit(0); ); Toolkit tk = Toolkit.getDefaultToolkit(); img = tk.getimage("getjava.gif"); setbounds(100,100, 400,300); setvisible(true); public static void main(string[] args) { new GraphicsEx6("GraphicsEx6"); public void paint(graphics g) { if(img==null) return; // Image 의크기를얻는다. int imgwidth = img.getwidth(this); // getwidth(imageobserver obj) int imgheight = img.getheight(this); // getheight(imageobserver obj) // 이미지를 Frame 의중앙에출력한다. g.drawimage(img,(getwidth()-imgwidth)/2, (getheight()-imgheight)/2, this); // class [ 실행결과] getjava.gif 라는이미지를화면의중앙에보여주는예제이다. 파일명은경로를함께지정해주 는것이좋으며, 예제의클래스파일과같은경로에있는경우경로명을생략할수있다.

772 Java의정석定石 2판 8. 애플릿(Applet) 인터넷초기에애플릿(Applet) 의등장은획기적인것이었다. 인터넷을통해서프로그램이자 동으로다운로드되고실행된다는것은당시로서는정말놀라운일이아닐수없었다. 게다가지금과는달리단순한텍스트위주의홈페이지를꾸밀수있는유일한방법이기도했 기때문에애플릿의인기는실로대단한것이었다. 더불어자바의인기도급상승하여 자바는 애플릿 이라는등식이성립하기도하였으나애플릿은플래시와 Ajax와같은새로등장한인 터넷기술들에밀려지금은예전에비해잘사용되지않고있다. 그래도여전히애플릿은유용하며애플릿의기본적인내용에대해서는알아두는것이좋기 때문에애플릿에대한필수적인내용들을설명하고자한다. JDK 설치경로\demo\applets 에가면여러종류의데모애플릿을볼수있는데이들을 살펴보면애플릿으로어떤일들을할수있는지이해하기쉬울것이다. 8.1 애플릿(Applet) 이란? 애플릿은작은어플리케이션이란뜻으로웹브라우저를통해실행될수있는자바클래스를말 한다. 자바어플리케이션은 java.exe를통해 main 메서드가호출되면서실행되지만, 애플릿은 main 메서드가필요하지않으며웹브라우저를통해서실행된다. 그외에도다음과같은어플 리케이션과는다른몇가지특징을가지고있다. 1. 애플릿관련정보가포함된 HTML 문서를작성해야한다. 2. java.exe 가아닌웹브라우저를통해실행된다. 3. public static void main(string args[]) 이필요없다. 4. 애플릿은 java.applet.applet을상속하는 public 클래스이어야한다. 모든애플릿이상속받아야하는 java.applet.applet의조상은 java.awt.panel이기때문에애 플릿은일반 AWT 어플리케이션을작성하는것과다르지않다. Panel이다른컴포넌트를포 함할수있는컨테이너인것처럼, 애플릿역시 Button이나 TextField를추가할수도있고메 뉴를추가하는것도가능하다. Object Component Container Panel Applet Window [ 그림13-15] 애플릿의상속계층도 [ 예제13-46]/ch13/HelloApplet.java import java.awt.*; public class HelloApplet extends java.applet.applet { public void paint(graphics g) {

Chapter 13 AWT 와애플릿(Applet) 773 setbackground(color.lightgray); // 애플릿의바탕을밝은회색으로설정 g.drawstring("hello, Applet.",50,50); AppletTest.html <html> <applet code="helloapplet.class" width=200 height=100> </applet> </html> [ 실행결과] 애플릿을실행하려면 AppletTest.html 을웹브라우저로열면된다. 애플릿클래스파일인 HelloApplet.class파일은 AppletTest.html 과같은디렉토리에위치하거나 <applet> 태그에 옵션을사용해서각각의경로를지정해주어야한다. [ 참고] <applet> 태그의옵션은 p.778을참고하자 애플릿을실행하는또다른방법은애플릿뷰어(appletviwer.exe) 를사용하는것이다. 애플릿 뷰어는최소한의기능을가진웹브라우저로애플릿을테스트해보기에좋은환경을제공한다. 애플릿뷰어로 HelloApplet 을실행하려면다음과같이하면된다. C:\jdk1.5\work\ch13>appletviewer AppletTest.html [ 그림13-16] 애플릿뷰어로실행한화면

774 Java의정석定石 2판 알아두면좋아요! - 애플릿디버깅 웹브라우저에서콘솔창을열어두면애플릿을디버깅하는데도움이된다. 애플릿에서 System.out.println() 을이용해서출력하는내용이나예외가발생하면콘솔창에나타난다. [ 그림13-17] 웹브라우저에서 Sun Java 콘솔 메뉴를선택한화면 [ 그림13-18] Java콘솔이실행된화면

Chapter 13 AWT 와애플릿(Applet) 775 8.2 Applet 의생명주기(Life cycle) 와주요메서드 어플리케이션은클래스파일의 한정보가담긴 main 메서드가호출되면서시작되지만, 애플릿은실행에필요 HTML 을웹브라우저가읽는것으로부터실행이시작된다. 애플릿이실행되는과정을단계별로살펴보면다음과같다. 1. 웹브라우저가애플릿이포함된 HTML 문서를읽는다. 2. 웹브라우저가애플릿( 자바클래스) 을다운로드한다. 3. 웹브라우저가애플릿의인스턴스를생성한다. 4. 애플릿이초기화된다. - init() 이호출된다. 5. 애플릿이실행된다. - start() 가호출된다. 애플릿은일반어플리케이션과는달리 이메서드들은상황에따라웹브라우저에내장된 init(), start() 와같은특별한메서드들을가지고있다. JVM에의해자동적으로호출되는것들이 므로언제호출되는지잘알아두고각메서드를용도에맞게오버로딩해야한다. 애플릿의메서드 init() start() stop() destroy() 설명 애플릿이생성될때호출된다. 객체생성이나이미지로딩등, 애플릿의 초기화작업에사용된다. 생성자다음에호출된다. 애플릿의실행이시작또는재시작될때호출된다. 웹브라우저가아이콘 화되었다가화면에다시나타날때그리고 반드시호출된다. init() 이호출된직후에는 애플릿의실행을중지시킨다. 웹브라우저가아이콘화되던가, 다른페이 지로이동할때, 그리고 destroy() 가호출되기직전에반드시호출된다. 웹브라우저가닫히면서애플릿이소멸되기직전에 stop() 다음으로호출 된다. 애플릿이사용하던자원을반환하는용도로사용된다. [ 표13-29] 애플릿의생명주기와관련된메서드 애플릿이화면에보이지않는동안에도불필요하게 에화면에서보이지않을때는 다가다시화면에나타나면 CPU를점유하는것을막기위해애플릿 stop() 이자동적으로호출되어애플릿의실행을일시중지시켰 start() 가호출되어애플릿이실행을계속하도록되어있다. 그러나웹브라우저의종류에따라위의메서드가호출되는시점이다를수있기때문에애플 릿이서비스될웹브라우저에서각메서드가호출되는시기를반드시테스트해봐야한다. [ 예제13-47]/ch13/AppletEx1.java import java.awt.*; import java.awt.event.*; public class AppletEx1 extends java.applet.applet { TextArea ta = new TextArea(); Button clear = new Button("clear"); public AppletEx1() { setlayout(new BorderLayout()); add(ta,"center");

776 Java의정석定石 2판 add(clear,"south"); clear.addactionlistener(new ActionListener() { public void actionperformed(actionevent e) { ta.settext(""); ); write("constructor\n"); public void init() { write("init()\n"); public void start() { write("start()\n"); public void stop() { write("stop()\n"); public void destroy() { write("destroy()\n"); public void paint(graphics g) { write("paint()\n"); public void write(string str) { ta.append(str); System.out.print(str); AppletEx1.html <html> <applet code="appletex1.class" width=200 height=100> </applet> </html> [ 실행결과] 애플릿을실행했을때호출되는메서드의순서를확인할수있는예제이다. TextArea에출력 하기때문에 stop() 과 destory() 가호출되는시점을확인하기어려워서 System.out. print() 를사용해서웹브라우저의콘솔에도출력되도록하였다. 웹브라우저의콘솔을열어놓고, 웹브라우저를아이콘화했다가다시화면에나타나게했을 때, 웹브라우저의 새로고침(reload) 버튼 을눌렀을때, 다른페이지로이동했다가다시애플 릿이있는페이지로되돌아왔을때어떤순서로어떤메서드들이호출되는지확인해보자.

Chapter 13 AWT 와애플릿(Applet) 777 애플릿뷰어를사용해서이예제를실행하면 stop() 과 destroy() 가호출되는시점을확인할수 있다. 그러나웹브라우저의종류에따라호출되는시점이다르기때문에반드시애플릿이서 비스될웹브라우저에서테스트를해보아야한다. 8.3 Applet 의보안제약(Security restriction) 애플릿은네트웍을통해외부로부터자동으로다운받는프로그램이기때문에보안상잠재적 인위험요소를가지고있다. 외부로부터다운로드받은프로그램이자신의컴퓨터에서제약없이어떠한일이든할수있 도록허락하는것은얼마나위험한일이겠는가. 만일누군가에의해악의적으로작성된애플릿이사용자의컴퓨터로부터몰래정보를빼낸 다던가또는중요한파일을변경, 삭제하거나심지어하드드라이브를포맷한다면정말큰일 이아닐수없다. 그래서사용자들이애플릿을안심하고사용할수있도록, 자바어플리케이션과는달리, 애플 릿에는다음과같은작업을수행하는것이금지되어있다. 1. 사용자의컴퓨터에있는실행파일(calc.exe) 을실행하는것 Runtime rt = Runtime.getRuntime(); rt.exec("c:\\windows\\system32\\calc.exe"); // 계산기를실행시킨다. 2. 사용자컴퓨터의파일을읽거나쓰기 FileWriter fw = new FileWriter("test.txt"); // test.txt에 abc 를출력한다. fw.write("abc"); 3. 사용자컴퓨터의정보를읽기 String username = System.getProperty("user.name"); // 사용자계정 String dir = System.getProperty("java.home"); // JDK가설치된위치 4. 애플릿을제공한서버가아닌다른컴퓨터에서소켓열기 5. 네이티브메서드(native method) 호출 만일애플릿에서위와같은작업을시도하면예외(AccessControlException) 가발생한다. 그러나애플릿에대한제약을풀방법이전혀없는것은아니다. jarsigner.exe와 keytool.exe 를사용해서서명된애플릿(Signed Applet) 으로만들거나 policytool.exe를이 용해서정책파일(java.policy) 을변경하면지정된 URL을통해서다운로드된애플릿에대해 서는제약의일부또는전체를풀어줄수있다. 자세한내용은 'JDK 설치경로/docs/tooldocs/index.html' 를참고하자. [ 참고] keytool.exe, jarsigner.exe 등은 'JDK 설치경로/bin' 디렉토리에있으며, java.policy 파일은 'JDK설치경로 /jre/lib/security/' 디렉토리에있다. [ 참고] 대부분의사용자시스템관련정보는접근할수없지만, 파일구분자(file.separator), 경로구분자 (path.separator) 등의일부정보는접근을허용한다. java.policy파일의내용을보면어떠한속성들에대한접근 을허용하는지확인할수있다.

778 Java의정석定石 2판 8.4 Applet과 HTML태그 애플릿을 HTML 페이지에포함시킬때 <APPLET> 를사용한다는것은이미배웠지만, 이태 그에는 다음은 CODE 옵션외에도여러가지옵션들이있다. <APPLET> 태그에사용할수있는필수옵션과선택옵션을모두표시한것이다. 대괄 호[] 로감싸인옵션은생략할수있는선택옵션이다. <APPLET [ARCHIVE=archiveList] CODE=appletFile.class WIDTH=pixels HEIGHT=pixels [CODEBASE=codebaseURL] [ALT=alternateText] [NAME=appletInstanceName] [ALIGN=alignment] [VSPACE=pixels] [HSPACE=pixels] > [<PARAM NAME=appletAttribute1 VALUE=value>] [<PARAM NAME=appletAttribute2 VALUE=value>]... </APPLET> 태그옵션 ARCHIVE CODE WIDTH, HEIGHT CODEBASE ALT NAME ALIGN 설명 애플릿에사용되는클래스파일이나이미지파일이담긴 jar파일을지정하는데사 용된다. jar 파일이하나이상일때는쉼표(,) 를구분자로사용한다. 예 : ARCHIVE="a.jar, b.jar" 애플릿클래스의클래스파일을지정하는데사용한다. 패키지명. 클래스명.class 형태로지정한다. 애플릿이웹브라우저에보여질영역의폭(WIDTH) 과넓이(HEIGHT) 를지정하는데 사용된다. 애플릿을다운로드할경로(URL) 를지정하는데사용된다. 이옵션이없으면애 플릿이담긴 HTML의경로가 codebase 가된다. <APPLET> 태그를이해하지못하는웹브라우저에서애플릿대신보여줄텍스트를 지정하는데사용한다. 애플릿의이름을지정하는데사용한다. 하나의 HTML페이지에둘이상의애플릿 이있을때서로구별되도록할수있다. 애플릿의정렬위치(alignment) 를지정하는데사용된다. HTML의태그에사용되는 align 옵션과동일한값이사용될수있다. 예를들면 left, right, top, bottom 등의값이사용된다. VSPACE, HSPACE 애플릿의외부여백을지정하는데사용된다. <PARAM NAME=attribute VALUE=value> 외부에서애플릿에값을전달할때사용한다. 자바어플리케이션을실행할때 커맨드라인에서값을입력하는것과유사하다. 애플릿내부에서는 getparameter(string name) 을사용해서값을읽을수있다. [ 표13-30] 애플릿의생명주기와관련된메서드

Chapter 13 AWT 와애플릿(Applet) 779 [ 예제13-48]/ch13/AppletEx2.java import java.awt.*; import java.awt.event.*; import java.applet.applet; public class AppletEx2 extends Applet implements MouseMotionListener { int x = 0; int y = 0; Image img = null; Graphics gimg = null; public AppletEx2() { addmousemotionlistener(this); public void init() { img = createimage(500, 500); gimg = img.getgraphics(); gimg.drawstring(getparameter("text"),10, 50); gimg.drawstring("value1:"+getparameter("value1"),10, 65); gimg.drawstring("value2:"+getparameter("value2"),10, 80); public void paint(graphics g) { if(img==null) return; g.drawimage(img,0,0,this); // 가상화면에그려진그림을 Frame에복사 public void mousemoved(mouseevent me) { x = me.getx(); y = me.gety(); public void mousedragged(mouseevent me) { if (me.getmodifiersex()!=mouseevent.button1_down_mask ) return; gimg.drawline(x,y, me.getx(),me.gety()); x = me.getx(); y = me.gety(); repaint(); // class AppletEx2.html <html> <applet code="appletex2.class" width=500 height=500> <param name="value1" value="100"> <param name="value2" value="200"> <param name="text" value=" 왼쪽버튼을누른채로마우스를움직여보세요."> </applet> </html>

780 Java의정석定石 2판 [ 실행결과] 이전의 AWT 예제13-44 를애플릿으로그대로옮긴것이다. 다른점이있다면 getparameter (String name) 를이용해서 HTML 문서로부터값을읽어서애플릿에서사용했다는것이다. 자바어플리케이션이커맨드라인을통해서외부로부터값을입력받을수있는것과같이애 플릿도 HTML문서의 pararm 태그로부터값을제공받아사용할수있다. public void init() { img = createimage(500, 500); gimg = img.getgraphics(); gimg.drawstring(getparameter("text"),10, 50); gimg.drawstring("value1:"+getparameter("value1"),10, 65); gimg.drawstring("value2:"+getparameter("value2"),10, 80); [ 예제13-49]/ch13/AppletEx3.java import java.awt.*; import java.applet.applet; public class AppletEx3 extends Applet { Image img = null; public void init() { img = getimage(getdocumentbase(), getparameter("imgname")); public void paint(graphics g) { // Image 의크기를얻는다. int imgwidth = img.getwidth(this); // getwidth(imageobserver obj) int imgheight = img.getheight(this); //getheight(imageobserver obj) // 이미지를 Frame 의중앙에출력한다.

Chapter 13 AWT 와애플릿(Applet) 781 g.drawimage(img, (getwidth()-imgwidth)/2, (getheight()-imgheight)/2, this); // class AppletEx3.html <html> <applet code="appletex3.class" width=500 height=500> <param name="imgname" value="getjava.gif"> </applet> </html> [ 실행결과] 애플릿에서이미지파일을출력하는예제이다. 이예제역시전의 AWT 예제13-45를애플릿 으로변경한것이기때문에별도의설명은필요없을것같다. 그래도예제에사용된메서드 에대해서는간단히정리하고넘어가겠다. Image getimage(url url, String image) - 지정된주소(URL) 의이미지(image) 를 Image 객체로반환한다. URL getdocumentbase() - 애플릿이포함된 HTML 의주소(URL) 를반환한다. URL getcodebase() - 애플릿클래스파일이저장되어있는주소(URL) 를반환한다. 지금까지 AWT 와애플릿에대해서알아봤는데부족한부분이없지않을것이다. 그래도일단 AWT를통해서 GUI어플리케이션이어떤것인지이해하고간단히활용할수있을정도로만 학습해두길바란다. 실무에서는자바가 더깊이있게학습하면좋을것같다. GUI어플리케이션에서많이사용되고있지않기때문에후에필요할때

782 Java의정석定石 2판 [ 연습문제 ] [13-1] 아래의실행결과처럼가로, 세로크기가 5 인빙고판을만드시오. 그리고버튼을 누르면, 버튼의배경색이밝은회색(Color.LIGHT_GRAY) 으로바뀌고누른버튼의글자가 콘솔에출력되게하시오. [ 실행결과]

Chapter 13 AWT 와애플릿(Applet) 783 [13-2] 다음중기본레이아웃매니저가 BorderLayout 이아닌컨테이너는? ( 모두고르 시오 ) a. Window b. Panel c. Applet d. Frame e. Dialog [13-3] 다음중 ActionEvent 가발생하는경우가아닌것은? ( 모두고르시오) a. Button 을클릭했을때 b. Menu 를클릭했을때 c. TextArea에서 Enter키를눌렀을때 d. List에서 item을선택하여클릭했을때 e. Label 을더블클릭했을때 [13-4] 타이틀바에현재시간을출력하는시계를작성하시오. 단, 쓰레드를이용해서 시간이 [Hint] 1 초마다계속변경되도록해야한다. SimpleDateFormat 을사용하라. [ 실행결과]

784 Java의정석定石 2판 [13-5] 다음의코드는현재년과월을보여주고왼쪽의버튼을누르면이전달로, 오른 쪽버튼을누르면다음달로이동하는프로그램이다. 알맞은코드를넣어프로그램을완 성하시오. [ 연습문제]/ch13/Exercise13_5.java import java.io.*; import java.util.*; import java.text.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.border.*; class Exercise13_5 extends Frame { Panel pup = new Panel(); Button btnprevmon = new Button(" "); Button btnnextmon = new Button(" "); Label lblyearmon = new Label(); Calendar curmon = Calendar.getInstance(); Exercise13_5(String title) { super(title); pup.setbackground(color.yellow); pup.setlayout(new FlowLayout(FlowLayout.CENTER)); pup.add(btnprevmon); pup.add(lblyearmon); pup.add(btnnextmon); btnprevmon.addactionlistener(new BtnEventHandler()); btnnextmon.addactionlistener(new BtnEventHandler()); addwindowlistener(new WindowAdapter() { public void windowclosing(windowevent we) { we.getwindow().setvisible(false); we.getwindow().dispose(); System.exit(0); ); add(pup); setbounds(200,200,200,70); setdays(curmon); setvisible(true); // Exercise13_5 void setdays(calendar date) { int year = date.get(calendar.year); int month = date.get(calendar.month); lblyearmon.settext(year+" 년 "+(month+1)+" 월"); class BtnEventHandler implements ActionListener { public void actionperformed(actionevent ae) {

Chapter 13 AWT 와애플릿(Applet) 785 /* */ (1) 아래의로직에맞게코드를작성하시오. 1. 눌러진버튼이 btnprevmon 이면, curmon 을한달이전으로변경한다. 2. 눌러진버튼이 btnnextmon 이면, curmon 을한달이후로변경한다. 3. setdays() 를호출해서변경된내용이레이블에보이게한다. public static void main(string[] args) { Exercise13_5 mainwin = new Exercise13_5("Scheduler"); // main [ 실행결과]

786 Java의정석定石 2판 [13-6] 다음의코드는문제13-5를발전시켜서해당월의날짜를버튼으로추가하는코드 이다. (1)~(2) 에알맞은코드를넣어프로그램을완성하시오. [ 연습문제]/ch13/Exercise13_6.java import java.io.*; import java.util.*; import java.text.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.border.*; class Exercise13_6 extends Frame { Panel pdate = new Panel(); Panel pup = new Panel(); Button btnprevmon = new Button(" "); Button btnnextmon = new Button(" "); Label lblyearmon = new Label(); Button[] btnarr = new Button[42]; Calendar curmon = Calendar.getInstance(); Exercise13_6(String title) { super(title); pup.setbackground(color.yellow); pup.setlayout(new FlowLayout(FlowLayout.CENTER)); pup.add(btnprevmon); pup.add(lblyearmon); pup.add(btnnextmon); pdate.setlayout(new GridLayout(6,7)); for(int i=0; i < btnarr.length;i++) { btnarr[i] = new Button(""); pdate.add(btnarr[i]); btnprevmon.addactionlistener(new BtnEventHandler()); btnnextmon.addactionlistener(new BtnEventHandler()); addwindowlistener(new WindowAdapter() { public void windowclosing(windowevent we) { we.getwindow().setvisible(false); we.getwindow().dispose(); System.exit(0); ); add(pup,"north"); add(pdate,"center"); setbounds(200,200,500,300); setdays(curmon); setvisible(true);

Chapter 13 AWT 와애플릿(Applet) 787 // MyScheduler void setdays(calendar date) { int year = date.get(calendar.year); int month = date.get(calendar.month); lblyearmon.settext(year+" 년 "+(month+1)+" 월"); Calendar sday = Calendar.getInstance(); // 시작일 /* (1) 아래의로직에맞게코드를작성하시오. 1. 시작일(sDay) 을해당월의 1 일이포함된일요일로설정한다. 2. 반복문을사용해서 sday의값을 1 씩증가시키면서버튼에날짜를넣는다. 3. 만일날짜가해당월에속하면버튼의배경색을흰색(Color.white) 으로하고그렇지않으면밝은회색(Color.lightGray) 으로설정한다. */ // setdays(calendar date) class BtnEventHandler implements ActionListener { public void actionperformed(actionevent ae) { /* (2) 아래의로직에맞게코드를작성하시오. 1. 눌러진버튼이 btnprevmon 이면, curmon 을한달이전으로변경한다. 2. 눌러진버튼이 btnnextmon 이면, curmon 을한달이후로변경한다. 3. setdays() 를호출해서변경된내용이레이블에보이게한다. */ public static void main(string[] args) { Exercise13_6 mainwin = new Exercise13_6("Scheduler"); // main [ 실행결과]

788 Java의정석定石 2판 [13-7] 다음의코드는오목게임이다. Frame 에오목판을그리고, 그위에왼쪽버튼을누 르면검은돌이오른쪽버튼을누르면흰돌이그려지도록알맞은코드를완성하시오. 단, 돌은클릭한곳의가장가까운교차점에놓여야한다. [ 연습문제]/ch13/Exercise13_7.java import java.awt.*; import java.awt.event.*; class Exercise13_7 extends Frame implements MouseListener { final int LINE_NUM = 9; // 오목판줄수 final int LINE_WIDTH = 30; // 오목판줄간격 final int BOARD_SIZE = LINE_WIDTH * (LINE_NUM-1); // 오목판의크기 final int STONE_SIZE = (int)(line_width * 0.8); // 돌의크기 final int X0; // 오목판시작위치 x좌표 final int Y0; // 오목판시작위치 y좌표 final int FRAME_WIDTH; // Frame의폭 final int FRAME_HEIGHT; // Frame의높이 Image img = null; Graphics gimg = null; public Exercise13_7(String title) { super(title); // Event Handler 를등록한다. addmouselistener(this); addwindowlistener(new WindowAdapter() { public void windowclosing(windowevent we) { System.exit(0); ); setvisible(true); // Frame 을화면에보이게한다. Insets insets = getinsets(); // 화면에보이기전에는 Insets 의값을얻을수없다. // 오목판그려질위치(LEFT, TOP) 의좌표 X0, Y0 를지정한다. X0 = insets.left + LINE_WIDTH; Y0 = insets.top + LINE_WIDTH; // Frame 의크기를계산한다. FRAME_WIDTH = BOARD_SIZE+LINE_WIDTH*2+insets.left+insets.right; FRAME_HEIGHT = BOARD_SIZE+LINE_WIDTH*2+insets.top+insets.bottom; // Frame 을화면의 (100,100) 의위치에계산된크기로보이게한다. setbounds(100,100, FRAME_WIDTH, FRAME_HEIGHT); img = createimage(frame_width, FRAME_HEIGHT); gimg = img.getgraphics(); setresizable(false); // Frame 의크기를변경하지못하게한다. drawboard(gimg); // Exercise13_7(String title) public void drawboard(graphics g) {

Chapter 13 AWT 와애플릿(Applet) 789 for(int i=0; i<line_num;i++) { g.drawline(x0,y0+i*line_width,x0+board_size, Y0+i*LINE_WIDTH); g.drawline(x0+i*line_width,y0, X0+i*LINE_WIDTH, Y0+BOARD_SIZE); public void paint(graphics g) { if(img==null) return; g.drawimage(img,0,0,this); // 가상화면에그려진그림을 Frame에복사 public void mousepressed(mouseevent e) { int x = e.getx(); // 마우스포인터의 x좌표 int y = e.gety(); // 마우스포인터의 y좌표 // MouseListener /* (1) 아래의로직에맞게코드를작성하시오. 1. x와 y 의값이오목판의밖을벗어난곳이면돌을그리지않는다. 2. x와 y 의값을클릭한곳에서가장가까운교차점으로변경한다.( 반올림) 3. x와 y 의값에서돌의크기(STONE_SIZE) 의절반을빼야클릭한곳에돌이그려진다. 4. 눌러진버튼이마우스왼쪽버튼이면, (x,y) 의위치에검은돌을그리고눌러진버튼이마우스오른쪽버튼이면, (x,y) 의위치에흰돌을그린다. ( 흰돌을그릴때검은색테두리도같이그린다.) 5. repaint() 를호출한다. */ public void mouseclicked(mouseevent e) { // MouseListener public void mouseentered(mouseevent e) { // MouseListener public void mouseexited(mouseevent e) { // MouseListener public void mousereleased(mouseevent e) { // MouseListener public static void main(string[] args) { new Exercise13_7("OmokTest"); [ 실행결과]

790 Java의정석定石 2판 [13-8] 다음은 Frame 의내부를튀어다니는공을그리는프로그램이다. 공이 Frame의 벽에부딪히면방향을바꾸어이동한다. 알맞은코드를넣어완성하시오. [ 연습문제]/ch13/Exercise13_8.java import java.awt.*; import java.awt.event.*; class BouncingBall extends Frame { final int BALL_SIZE = 20; final int FRAME_WIDTH = 400; final int FRAME_HEIGHT = 300; final int TOP; final int BOTTOM; final int LEFT; final int RIGHT; final int SPEED = 3; int x = 100; int y = 100; int xstep = SPEED; int ystep = SPEED; BouncingBall(String title) { super(title); addwindowlistener(new WindowAdapter() { public void windowclosing(windowevent e) { System.exit(0); ); setbounds(300,200, FRAME_WIDTH, FRAME_HEIGHT); setresizable(false); setvisible(true); Insets insets = getinsets(); // Frame 의테두리의두께를얻어온다. TOP = insets.top; LEFT = insets.left; BOTTOM = FRAME_HEIGHT - insets.bottom ; RIGHT = FRAME_WIDTH - insets.right; void start() { while(true) { x +=xstep; y +=ystep; /* (1) 아래의로직에맞게코드를작성하시오. 1. x 의값이왼쪽테두리(LEFT) 보다작거나같으면 x의값을 LEFT로바꾸고 x 축이동방향(xStep) 을반대로한다.

Chapter 13 AWT 와애플릿(Applet) 791 2. x 의값이오른쪽테두리(RIGHT-BALL_SIZE) 보다작거나같으면 x의값을 RIGHT-BALL_SIZE로바꾸고 x 축이동방향(xStep) 을반대로한다. 3. y 의값이윗쪽테두리(TOP) 보다작거나같으면 y의값을 TOP으로바꾸고 y 축이동방향(yStep) 을반대로한다. 4. y 의값이아래쪽테두리(BOTTON-BALL_SIZE) 보다작거나같으면 y의값을 BOTTON-BALL_SIZE로바꾸고 y 축이동방향(yStep) 을반대로한다. */ repaint(); try { Thread.sleep(100); catch (Exception e) { // start() public void paint(graphics g) { g.setcolor(color.red); g.filloval(x, y, BALL_SIZE, BALL_SIZE); class Exercise13_8 { public static void main(string[] args) { new BouncingBall("Bouncing Ball").start(); [ 실행결과]

792 Java의정석定石 2판 [13-9] 문제13-8을발전시켜서 BallGenerator라는쓰레드를생성시켜서 3초마다새로운 공을하나씩생성하는프로그램이다. 알맞은코드를넣어프로그램을완성하시오. [ 연습문제]/ch13/Exercise13_9.java import java.util.*; import java.awt.*; import java.awt.event.*; class BouncingBall extends Frame { final int FRAME_WIDTH = 400; final int FRAME_HEIGHT = 300; final int TOP; final int BOTTOM; final int LEFT; final int RIGHT; ArrayList balls = new ArrayList(); BouncingBall(String title) { super(title); setbounds(300,200, FRAME_WIDTH, FRAME_HEIGHT); setresizable(false); setvisible(true); Insets insets = getinsets(); TOP = insets.top; LEFT = insets.left; BOTTOM = FRAME_HEIGHT - insets.bottom; RIGHT = FRAME_WIDTH - insets.right; addwindowlistener(new WindowAdapter() { public void windowclosing(windowevent e) { System.exit(0); ); void start() { new BallGenerator().start(); while(true) { int size = balls.size(); for(int i=0 ; i < size; i++) { Ball b = (Ball)balls.get(i); b.x +=b.xstep; b.y +=b.ystep; /* (1) 아래의로직에맞게코드를작성하시오. 1. x 의값이왼쪽테두리(LEFT) 보다작거나같으면

Chapter 13 AWT 와애플릿(Applet) 793 x의값을 LEFT로바꾸고 x 축이동방향(xStep) 을반대로한다. 2. x 의값이오른쪽테두리(RIGHT-BALL_SIZE) 보다작거나같으면 x의값을 RIGHT-BALL_SIZE로바꾸고 x 축이동방향(xStep) 을반대로한다. 3. y 의값이윗쪽테두리(TOP) 보다작거나같으면 y의값을 TOP으로바꾸고 y 축이동방향(yStep) 을반대로한다. 4. y 의값이아래쪽테두리(BOTTON-BALL_SIZE) 보다작거나같으면 y의값을 BOTTON-BALL_SIZE로바꾸고 y 축이동방향(yStep) 을반대로한다. */ repaint(); try { Thread.sleep(100); catch (Exception e) { // start() public void paint(graphics g) { g.drawstring("number of balls :"+balls.size(),20,50); g.setcolor(color.red); int size = balls.size(); for(int i=0 ; i < size; i++) { Ball b = (Ball)balls.get(i); g.filloval(b.x, b.y, Ball.SIZE, Ball.SIZE); class BallGenerator extends Thread { public void run() { /* (2) 아래의로직에맞게코드를작성하시오. 1. 3초마다 Frame의임의의위치에공을생성해서 balls 에추가한다. */ // run() class Ball { int x = 100; int y = 100; static final int SIZE = 30; final int SPEED = 5; int xstep = SPEED; int ystep = SPEED; Ball(int x, int y) { this.x = x; this.y = y; // class BouncingBall

794 Java의정석定石 2판 class Exercise13_9 { public static void main(string[] args) { new BouncingBall("Bouncing Ball").start(); [ 실행결과]

Chapter 13 AWT 와애플릿(Applet) 795 [13-10] 다음은키보드의화살표키를이용해서공을 Frame의테두리내에서상하좌우로 이동시키는프로그램이다. 알맞은코드를넣어프로그램을완성하시오. [ 연습문제]/ch13/Exercise13_10.java import java.awt.*; import java.awt.event.*; class BouncingBall extends Frame { final int BALL_SIZE = 20; final int FRAME_WIDTH = 400; final int FRAME_HEIGHT = 300; final int TOP; final int BOTTOM; final int LEFT; final int RIGHT; int x; int y; final int SPEED = 3; int xstep = SPEED; int ystep = SPEED; BouncingBall(String title) { super(title); x = FRAME_WIDTH/2 - BALL_SIZE/2; y = FRAME_HEIGHT/2 - BALL_SIZE/2; setvisible(true); setbounds(300,200, FRAME_WIDTH, FRAME_HEIGHT); Insets insets = getinsets(); TOP = insets.top; LEFT = insets.left; BOTTOM = FRAME_HEIGHT - insets.bottom ; RIGHT = FRAME_WIDTH - insets.right; registereventhandler(); setresizable(false); void registereventhandler() { addwindowlistener(new WindowAdapter() { public void windowclosing(windowevent e) { System.exit(0); ); addkeylistener(new KeyAdapter() { public void keypressed(keyevent ke){ int key = ke.getkeycode(); if(key==keyevent.vk_up){ /*

796 Java 의정석定石 ); (1) 알맞은코드를넣으시오. */ else if(key==keyevent.vk_down){ /* (2) 알맞은코드를넣으시오. */ else if(key==keyevent.vk_left){ /* (3) 알맞은코드를넣으시오. */ else if(key==keyevent.vk_right){ /* (4) 알맞은코드를넣으시오. */ // public void keypressed(keyevent ke) void start() { while(true) { repaint(); try { Thread.sleep(100); catch (Exception e) { // start() public void paint(graphics g) { g.setcolor(color.light_gray); g.filloval(x, y, BALL_SIZE, BALL_SIZE); class Exercise13_10 { public static void main(string[] args) { new BouncingBall("Bouncing Ball").start(); [ 실행결과]

Chapter 13 AWT 와애플릿(Applet) 797 [13-11] 다음은문제13-9와 13-10을결합해서발전시킨것으로회색공을키보드로움직 여서빨간공들을피해다니다빨간공과회색공이충돌하면중단되는프로그램이다. 알맞은 코드를넣어코드를완성하시오. [ 연습문제]/ch13/Exercise13_11.java import java.util.*; import java.awt.*; import java.awt.event.*; class BouncingBall extends Frame { final int BALL_SIZE = 20; final int FRAME_WIDTH = 400; final int FRAME_HEIGHT = 300; final int TOP; final int BOTTOM; final int LEFT; final int RIGHT; final int SPEED = 7; int x; int y; boolean isplaying = true; ArrayList balls = new ArrayList(); BouncingBall(String title) { super(title); x = FRAME_WIDTH/2 - BALL_SIZE/2; y = FRAME_HEIGHT/2 - BALL_SIZE/2; setbounds(300,200, FRAME_WIDTH, FRAME_HEIGHT); setresizable(false); setvisible(true); Insets insets = getinsets(); TOP = insets.top; LEFT = insets.left; BOTTOM = FRAME_HEIGHT - insets.bottom; RIGHT = FRAME_WIDTH - insets.right; registereventhandler(); void registereventhandler() { addwindowlistener(new WindowAdapter() { public void windowclosing(windowevent e) { System.exit(0); ); addkeylistener(new KeyAdapter() { public void keypressed(keyevent ke){ if(!isplaying) return;

798 Java 의정석定石 int key = ke.getkeycode(); ); if(key==keyevent.vk_up){ /* (1) 알맞은코드를넣으시오. */ else if(key==keyevent.vk_down){ /* (2) 알맞은코드를넣으시오. */ else if(key==keyevent.vk_left){ /* (3) 알맞은코드를넣으시오. */ else if(key==keyevent.vk_right){ /* (4) 알맞은코드를넣으시오. */ // public void keypressed(keyevent ke) void start() { new BallGenerator().start(); while(isplaying) { int size = balls.size(); for(int i=0 ; i < size; i++) { Ball b = (Ball)balls.get(i); b.x +=b.xstep; b.y +=b.ystep; /* (5) 아래의로직에맞게코드를작성하시오. 1. b.x 의값이왼쪽테두리(LEFT) 보다작거나같으면 b.x의값을 LEFT로바꾸고 x 축이동방향(b.xStep) 을반대로한다. 2. b.x 의값이오른쪽테두리(RIGHT-b.size) 보다작거나같으면 b.x의값을 RIGHT-b.size로바꾸고 x 축이동방향(b.xStep) 을반대로한다. 3. b.y 의값이윗쪽테두리(TOP) 보다작거나같으면 b.y의값을 TOP으로바꾸고 y 축이동방향(b.yStep) 을반대로한다. 4. b.y 의값이아래쪽테두리(BOTTON-b.size) 보다작거나같으면 b.y의값을 BOTTON-b.size로바꾸고 y 축이동방향(b.yStep) 을반대로한다. */ // for repaint(); try { Thread.sleep(100); catch (Exception e) {

Chapter 13 AWT 와애플릿(Applet) 799 // start() boolean collisioncheck(ball b) { /* (6) 아래의로직에맞게코드를작성하시오. 1. 회색공의중심과빨간공의중심간의거리(distance) 가회색공의반지름(BALL_SIZE/2) 과빨간공의반지름(b.size/2) 보다같거나작으면 true를반환하고그렇지않으면 false 를반환한다. */ 회색공의위치가 (x, y) 일때, 중심좌표는 (x+ball_size/2, y+ball_size/2) 이다. 두점 (x1, y1) 과 (x2, y2) 간의거리는아래의공식으로구할수있다. Math.sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2)) public void paint(graphics g) { g.drawstring("number of balls :"+balls.size(),20,50); g.setcolor(color.light_gray); g.filloval(x, y, BALL_SIZE, BALL_SIZE); g.setcolor(color.red); int size = balls.size(); for(int i=0 ; i < size; i++) { Ball b = (Ball)balls.get(i); g.filloval(b.x, b.y, b.size, b.size); class BallGenerator extends Thread { public void run() { while(isplaying) { int x=(int)(math.random()*(right-left-ball.max_size))+left; int y=(int)(math.random()*(bottom-top-ball.max_size))+top; balls.add(new Ball(x,y)); try { Thread.sleep(3*1000); catch(exception e) { // run() class Ball { int x = 100; int y = 100; int size = 30; static final int MAX_SIZE = 30; static final int MIN_SIZE = 10;

800 Java의정석定石 2판 final int SPEED = 5; int xstep = SPEED; int ystep = SPEED; Ball(int x, int y) { this(x, y,(int)(math.random()*(max_size-min_size))+min_size); Ball(int x, int y, int size) { this.x = x; this.y = y; this.size = size; // class BouncingBall class Exercise13_11 { public static void main(string[] args) { new BouncingBall("Bouncing Ball").start(); [ 실행결과]