SWT(Standard Widget ToolKit)란, Eclipse 프로젝트로부터 제공되고 있는 GUI 작성용 툴 킷입니다. 머리 글자 「W」의 위제트(Widget)라고 하는 단어는, 프로그래머의 사이에서는 넓게 사용되고 있는 용어로, 버튼이나 메뉴, 스크롤 바라고 하는 유저 인터페이스(UI)의 컴퍼넌트(구성요소)를 가리킵니다.
본고에서는, SWT의 해설과 Eclipse를 이용한 SWT 어플리케이션의 작성 방법에 대하고 실천을 근거로 해 소개합니다.
본문중에서는, Eclipse의 버젼을 2.1.2, Eclipse 인스톨 디렉토리를 c:\eclipse로서 기술하고 있습니다.Eclipse의 버젼이 오르면, 플러그 인의 디렉토리명등이 바뀌는 일이 있기 때문에, 주의해 주십시오.
SWT의 특징
SWT는 원래, 미 IBM가 IDE(통합 개발 환경)인 Eclipse용으로 개발한 툴 킷입니다.Eclipse가 오픈 소스로서 제공되었는데 따라, IDE와 함께 Eclipse 프로젝트로부터 제공되도록(듯이) l가 되었습니다.
SWT의 특징은 이하대로입니다.(1) 경쾌한 동작
SWT는 JNI(Java Native Interface) 경유로 OS의 네이티브 API를 호출하고 있기 때문에, 경쾌하게 동작합니다.Eclipse 자신도 그 UI가 SWT로 작성되고 있습니다. Eclipse가 여기까지 넓게 보급한 이유에는, SWT의 경쾌한 동작에 의하는 곳(중)이 클 것입니다.
(2) 플랫폼·네이티브인 룩&필
UI의 묘화를 위해서 OS의 네이티브 API를 호출하고 있기 때문에, 플랫폼·네이티브인 어플리케이션과 같은 룩&필을 실현할 수 있습니다.
(3) Pure Java는 아니다
JNI를 사용하고 있기 때문에, Pure Java가 아닙니다.그 때문에, 플랫폼 마다 SWT용의 공유 라이브러리가 필요합니다.그렇다고는 하지만, 현상 Windows, Linux, Solaris, QNX, AIX, HP-UX, Mac OSX, Windows CE라고 한 폭넓은 OS에 SWT는 포팅 되고 있습니다.게다가 SWT의 라이센스는 재배포를 가능하게 하고 있는 것을 고려하면, Pure Java는 아니라고 해도 큰 문제는 되지 않을 것입니다.게다가 프로그래밍상의 주의점으로서는, 각 위제트가 가지는 dispose 메소드를 들 수 있습니다.SWT의 위제트는 Pure Java는 아니기 때문에, 일반적인 Java 오브젝트와 같이, 확보한 자원이 GC에 의해서 개방되지 않습니다.위제트를 파기할 경우에는 dispose 메소드를 명시적으로 호출할 필요가 있습니다.
(4) 어플리케이션·코드는 플랫폼비의존
어플리케이션은, Shell나 Button등의 SWT의 클래스를 사용해 개발됩니다.Shell나 Button는, 네이티브 API를 가지는 클래스 「OS」나 「Callback」 「COM」를 통해서 공유 라이브러리를 호출해, OS에 대해 묘화를 의뢰합니다.어플리케이션으로부터의 네이티브 API의 호출은 모두 Java VM, SWT에 의해서 은폐 됩니다. 그 때문에, SWT를 사용해 개발된 어플리케이션은, 플랫폼비의존이 됩니다. 원시 파일 만이 아니고, 종래대로 클래스 파일도 이식성이 있습니다.또, 기본적인 위제트는 플랫폼비의존입니다만, SWT에서는 플랫폼 고유의 기술도 이용하는 것이 가능합니다. 예를 들면 Windows에서는, IE를 ActiveX의 컴퍼넌트로서 화면에 붙인다, 라고 하는 처리도 SWT에 의해 실시할 수 있습니다.
(5) Eclipse의 플러그 인 개발에 필요
Eclipse는 SWT를 이용해 실장되고 있기 때문에, Eclipse를 확장하는 플러그 인을 개발하기 위해서는 SWT가 필요합니다. 플러그 인 개발에서는, JFace라고 하는 SWT를 이용해 실장된 확장 툴 킷을 사용할 수도 있습니다.이 경우에서도, JFace는 SWT를 완전하게는 은폐 하지 않기 때문에, SWT의 지식이 필요합니다.
(6) Eclipse와 같을 유연한 라이센스
SWT는 Eclipse와 같은 CPL(Common Public License)로 배포되고 있습니다.그 때문에 SWT를 사용한 어플리케이션의 원시 코드를 공개할 의무는 없고, 라이센스상의 제한(상용 이용 불가 등)도 없습니다.
이와 같이, Pure Java는 아니라고 하는 점이나, 현재 상태로서는 RAD 툴이 얼마 안되다고 하는 마이너스면은 있지만, Java로의 클라이언트 어플리케이션 작성에 대해서는, 그 동작 속도가 매우 매력적입니다.Visual Editor Project 발족
현재, SWT의 RAD 툴로 하고 있어 구두인가의 상용 플러그 인이 존재하고 있습니다만, Swing용의 툴과 비교하면 수가 적고, 또 무료로 사용할 수 있는 것은 기능도 충분하다고는 말할 수 없는 상황입니다.
그러나, Eclipse 프로젝트가 2003년 11월 18일에 발표한 Visual Editor Project의 발족에 의해, 이 상황은 일변할 가능성이 있습니다.
Visual Editor Project란, 오픈 소스의 비주얼 GUI 개발 환경을 작성 및 제공하는 프로젝트입니다.이 프로젝트에서는 현재, Swing에 대응한 레퍼런스 GUI 개발 환경을 제공하고 있습니다.그리고 SWT에도 대응해 나갈 예정입니다.
이 Visual Editor는, Eclipse 본체와 같게 IBM로부터 제공된 원시 코드를 베이스로서 개발이 시작되어 있습니다.또, IBM 만이 아니고, Advanced Systems Concepts, Canoo, Instantiations, Red Hat등도, SWT 서포트의 실현을 위해서 자원을 제공할 예정입니다.
또 막 시작한 프로젝트입니다만, 이 프로젝트의 성과에 의해, GUI의 개발에 대해도, 오픈 소스의 툴만으로 상용 IDE와 동등의 생산성을 실현할 수 있게 되겠지요.
이 프로젝트의 상세한 것에 대하여는, Eclipse Visual Editor Ploject의 사이트(http://www.eclipse.org/vep/)(을)를 봐 주세요.
SWT의 제공하는 컴퍼넌트
GUI를 가지는 어플리케이션을 개발하려면 , 사용하는 툴 킷이 어떠한 컴퍼넌트를 제공하고 있을까를 알고 있을 필요가 있습니다.SWT로 제공되고 있는 컴퍼넌트(위제트나 레이아웃등)에 대해서는, 본기사의 마지막 「참고:컴퍼넌트」(으)로 소개합니다.Java2 표준의 GUI 컴퍼넌트인 Swing에의 대응도 비교로서 기술해 두기 때문에, 참고로 해 주세요.
덧붙여 각 컴퍼넌트의 상세한 것에 대하여는, Eclipse의 메뉴로부터[헬프]->[헬프 목차]로 표시되는 헬프 윈도우로, [Platform 플러그 인·디벨로퍼·가이드]->[프로그라마즈·가이드]->[Standard Widget Toolkit] 부하의 헬프를 참조해 주세요. SWT의 사용 방법
SWT를 사용하려면 라이브러리를 입수할 필요가, Eclipse를 사용하고 개발을 실시하는 경우에는, Eclipse 본체에 부속되는 라이브러리를 사용할 수 있습니다.
SWT의 이용에는, 이하의 2개의 라이브러리가 필요합니다.SWT의 Java 라이브러리
SWT의 클래스가 포함되어 있는 jar 파일이 필요 Windows의 경우, 이하의 jar 라이브러리가 필요하다
C:\eclipse\plugins\org.eclipse.swt.win32_2.1.2\ws\win32\swt.jar
플랫폼마다의 공유 라이브러리
Windows의 경우는 이하의 공유 라이브러리가 필요하다
C:\eclipse\plugins\org.eclipse.swt.win32_2.1.2\os\win32\x86\swt-win32-2135.dll
어플리케이션의 배포 시에는, 어플리케이션의 클래스 파일(또는 jar 파일), SWT의 Java 라이브러리, 플랫폼마다의 공유 라이브러리를 세트로 해 배포합니다.
또 Eclipse를 사용하지 않는 경우에서도, Eclipse의 다운로드 페이지로부터 SWT 단체의 라이브러리를 입수할 수 있습니다.
Eclipse의 다운로드 페이지(http://download2.eclipse.org/downloads/index.php)(으)로부터, 「Latest Release」의 「2.1.2」를 클릭해, 「SWT Binary and Source」중에서 플랫폼에 응한 파일을 다운로드해 주세요.
SWT 단체의 라이브러리를 다운로드할 수 있는 「SWT Binary and Source」
SWT용의 프로젝트의 작성
SWT를 이용한 개발을 실시하기에 즈음해, Eclipse상에서 SWT용의 프로젝트를 작성합니다. SWT용, 이라고 해도 특히 어려운 것은 없습니다.상기로 말한 필요한 라이브러리의 설정을 실시합니다.
■프로젝트의 작성과 설정
[파일]->[신규]->[프로젝트]로[신규 프로젝트]다이얼로그를 열어,[Java]->[Java 프로젝트] 를 선택합니다.
[다음에]를 클릭해, 표시되는 페이지로 프로젝트명을 입력합니다.이번은 「swtPrj」라고 입력했습니다.
[다음에]를 클릭해, 표시되는 페이지로 빌드 설정을 정의합니다. 이번은 이하와 같이 했습니다.소스·폴더 swtPrj/src
디폴트 출력 폴더 swtPrj/bin
[도서관]탭을 클릭해, SWT의 Java 라이브러리를 지정합니다.[외부 JAR 의 추가]버튼을 클릭해, 표시되는[JAR 선택]다이얼로그로[SWT의 사용 방법]로 말한 SWT의 Java 라이브러리를 선택합니다.
[종료]버튼을 클릭해, 프로젝트를 작성합니다.
플랫폼 마다 준비되어 있는 공유 라이브러리는, SWT를 사용한 어플리케이션의 코딩시에는 필요하다고는 되지 않습니다만, 기동시나 디버그시에는 필요합니다.「SWT의 사용 방법」로 설명한 공유 라이브러리를, 프로젝트의 디렉토리에 카피해 주세요.본고에서는, C:\eclipse\plugins\org.eclipse.swt.win32_2.1.2Yos\win32\x86\swt-win32-2135. dll를 C:\eclipse\workspace\swtPrj에 카피했습니다.
만약 공유 라이브러리의 카피를 실시하고 싶지 않은 경우에는, 어플리케이션의 기동시에 Java VM의 인수 옵션으로서 「-Djava.library.path=C:\eclipse\plugins\org.eclipse.swt.win32_2.1.2\os\win32\x86 」를 지정하는 것도 실행할 수 있습니다.
■SWT의 소스의 설정
SWT의 소스를 SWT의 Java 라이브러리에 끈 붙여 두면, 개발중에 SWT의 클래스의 Javadoc 코멘트가 팝업 표시되므로 편리합니다.
패키지·익스플로러상의[swt.jar]를 오른쪽 클릭->[자산]으로 다이얼로그를 열어 주세요.[Java 소스의 첨부]->[외부 파일]을 선택해 「c:\eclipse\plugins\org.eclipse.platform.win32.source_2.1.2\
src\org.eclipse.swt.win32_2.1.2Yws\win32\swtsrc.zip」를 지정합니다.
SWT 단체로 다운로드했을 경우, 다운로드한 어카이브(archive)안에 swtsrc.zip가 존재하므로, 그것을 지정하면 좋을 것입니다.
SWT 어플리케이션을 만든다
여기에서는, 드디어 SWT를 사용한 개발을 실천적으로 해설해 갈 것입니다.
■작성하는 어플리케이션
이번은 SWT의 어플리케이션으로서 CSV 파일을 겉(표) 형식에서 표시하는 CSVViewer를 작성합니다.CSVViewer의 개관은, 이하와 같이 됩니다.
이 어플리케이션의 사양은, 이하대로입니다.
메뉴로부터, 읽어들이는 파일의 선택과 어플리케이션의 종료를 실시할 수 있다
읽어들이고 있는 파일명을, 텍스트 박스에 표시한다
CSV 파일의 내용은, 테이블을 사용해 표시한다.렬명은 「열 1」 「열 2」…로 CSV 파일의 최대열몇분만큼 표시한다
현재의 상황을 표시하기 위한 상태 바를 마련한다
테이블내의 행을 선택했을 때에, 행 번호를 표시한다
파일의 읽기에 걸린 시간을 표시한다
여기에서는, 이하의 차례로 어플리케이션의 작성을 실시합니다.
(1) 쉘(윈도우)의 생성
(2) 쉘에의 위제트(GUI 컴퍼넌트)의 배치
(3) CSV 읽어들여, 표시 처리의 실장
(4) 위제트에의 이벤트 청취자의 등록(처리의 추가)
쉘(윈도우)의 생성
우선 여기에서는, 윈도우를 표시할 수 있는 곳(중)까지 완성시킵니다.
Eclipse의 메뉴로부터,[파일]->[신규]->[클래스]에서 신규 Java 클래스 다이얼로그를 엽니다.이하대로 입력하고,[종료]버튼을 클릭합니다.
소스·폴더 swtPrj/src
패키지명 csvviewer
이름 CSVViewer
Eclipse가 생성한 코드를 이하와 같이 편집합니다.
package csvviewer;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
/**
* CSVViewer
*/
public class CSVViewer {
private Shell shell;
private Display display;
public Shell open(Display display) {
this.display = display;
shell = new Shell(display); // (2)
shell.setText("CSVViewer");
shell.open(); // (6)
return shell;
}
public static void main(String[] args) {
Display display = new Display(); // (1)
CSVViewer viewer = new CSVViewer();
Shell shell = viewer.open(display);
// 윈도우가 파기될 때까지 루프
while (!shell.isDisposed()) { // (7)
if (!display.readAndDispatch())
display.sleep();
}
display.dispose(); // (8)
}
}
일반적인 SWT 어플리케이션의 처리의 흐름은, 다음과 같이 됩니다(번호는 코드중의 번호에 대응하고 있습니다).
(1) SWT 세션을 나타내는 Display 오브젝트를 생성
(2) 어플리케이션의 메인·윈도우가 되는 1개이상의 Shell를 생성
(3) 윈도우내에서 필요한 다른 위제트를 생성
(4) 위제트의 사이즈나, 그 외의 필요한 상태를 초기화
(5) 처리를 실행할 필요가 있는 위제트에 청취자를 등록
(6) Shell를 연다
(7) 메인·윈도우가 파기될 때까지, Display 오브젝트의 readAndDispatch 메소드와 sleep 메소드로 루프
(8) 메인·윈도우가 파기되면, Display 오브젝트를 파기
여기까지의 CSVViewer에서는, 상기 중(1), (2), (6), (7), (8)를 실장하고 있습니다.상기의 원시 코드에 코멘트로서 기술되고 있는 번호라고 봐 비교해 주세요.
CSVViewer의 소스가 선택되고 있는 상태로, Eclipse의 메뉴로부터 「실행」->「다음을 실행」->「Java 어플리케이션」을 선택하면, 프로그램을 실행할 수 있습니다.이하와 같은 윈도우가 표시됩니다.
어플리케이션으로서는 더 이상 아무것도 할 수 없기 때문에, CSVViewer의 타이틀 바상의 「×」버튼을 클릭해, 종료해 주세요.
여기까지의 소스는,여기(으)로부터 다운로드해 주세요(파일명, 클래스명을 바꾸고 있습니다).
쉘에의 위제트(GUI 컴퍼넌트)의 배치
다음에, 「(3) 윈도우내에서 필요한 것 외의 위제트를 생성」이라고 「(4) 위제트의 사이즈나, 그 다른 필요한 상태를 초기화」를 실장합니다.
이하에서는, 수정 개소 마다 설명을 실시합니다.변경한 행은 강조 표시되어 있습니다.
■인스턴스 변수의 추가
다음에 다른 메소드로부터 조작되는 위제트는, 인스턴스 변수에 선언해 둡니다.
private Shell shell;
private Display display;
private Text textBox;
private Table table;
private Label statusBar;
private MenuItem mItemOpen;
textBox, table, statusBar, mItemOpen를 선언했습니다.
■GridLayout의 지정
CSVViewer의 open 메소드내에서, 위제트를 생성하기 전에, shell에 대해 GridLayout를 지정합니다.
this.display = display;
shell = new Shell(display);
shell.setText("CSVViewer");
shell.setLayout(new GridLayout(1, true));
GridLayout의 constructor 의 인수 numColumns에 1을 지정했으므로, shell에 추가되는 위제트는, 세로 1열에 늘어놓을 수 있습니다.
■Composite의 생성
shell의 설정의 다음에, 텍스트 박스와 테이블을 배치하기 위한 Composite를 생성합니다.
// 부품을 복수 배치할 수 있는 Composite를 생성
Composite comp = new Composite(shell, SWT.NO_FOCUS);
comp.setLayout(new GridLayout(1, true));
GridData compGrid = new GridData();
compGrid.horizontalAlignment = GridData.FILL;
compGrid.verticalAlignment = GridData.FILL;
compGrid.grabExcessHorizontalSpace = true;
compGrid.grabExcessVerticalSpace = true;
comp.setLayoutData(compGrid);
Composite에는 Shell 같이, GridLayout을 지정합니다.
또, GridData를 설정해, 친위제트가 되는 Shell의 GridLayout에 대해서 폭전체, 높이 전체에 퍼진 배치를 하도록(듯이) 하고 있습니다.
■텍스트 박스의 생성
Composite를 생성한 후, 단일행의 텍스트 박스를 작성합니다.친위제트에는 방금전 작성한 Composite를 지정합니다.
// 단일행 텍스트 박스를 작성
textBox = new Text(comp, SWT.SINGLE | SWT.BORDER);
textBox.setText("");
GridData textGrid = new GridData();
textGrid.horizontalAlignment = GridData.FILL;
textGrid.grabExcessHorizontalSpace = true;
textBox.setLayoutData(textGrid);
단일행인지, 복수행일까는, 생성시에 constructor 의 style라고 하는 플래그로 지정합니다.한층 더 이번은 보더()를 붙이도록(듯이) BORDER를 지정했습니다.플래그는, 비트 연산자 「|」으로 복수 지정할 수 있습니다.
또, GridData를 설정해, 친위제트가 되는 Composite의 GridLayout에 대해서 폭전체에 퍼진 배치를 하도록(듯이) 하고 있습니다.
■테이블의 작성
텍스트 박스에 잇고, CSV 파일의 데이터를 표시하기 위한 테이블을 생성합니다.친위제트에는, Composite를 지정합니다.
복수열을 취급하는 MULTI, 테이블내의 행을 선택했을 때, 1행 전체가 선택되도록(듯이) 하는 FULL_SELECTION, 보더를 붙이도록(듯이) BORDER를 지정해 있습니다.
// 테이블의 작성
table = new Table(comp,
SWT.MULTI | SWT.FULL_SELECTION | SWT.BORDER);
GridData tableGrid = new GridData();
tableGrid.horizontalAlignment = GridData.FILL;
tableGrid.verticalAlignment = GridData.FILL;
tableGrid.grabExcessHorizontalSpace = true;
tableGrid.grabExcessVerticalSpace = true;
table.setLayoutData(tableGrid);
// 선을 표시한다
table.setLinesVisible(true);
// 헤더를 가시로 한다
table.setHeaderVisible(true);
// 열의 헤더의 설정
TableColumn col = new TableColumn(table, SWT.LEFT);
col.setText("열 1");
col.setWidth(50);
또, GridData를 설정해, 친위제트가 되는 Composite의 GridLayout에 대해서 폭전체, 높이 전체에 퍼진 배치를 하도록(듯이) 하고 있습니다.
괘선을 표시하기 위한 setLinesVisible 메소드, 열의 헤더를 표시하기 위한 setHeaderVisible 메소드를 부르고 있습니다.
또, 열의 헤더의 설정을 실시합니다.여기서 설정하는 것은 CSV 파일을 읽어들이지 않은 상태로 표시되는 테이블이므로, 우선 1렬분만큼 설정합니다.
■상태 바의 작성
SWT에서는 상태 바라고 하는 위제트는 존재하지 않기 때문에, 문자를 표시하는 라벨을 설정합니다.친위제트에 Shell를 지정합니다.
// 상태 바의 작성
statusBar = new Label(shell, SWT.LEFT);
GridData gridData = new GridData();
gridData.horizontalAlignment = GridData.FILL;
statusBar.setLayoutData(gridData);
statusBar.setText("메뉴로부터 CSV 파일을 지정해 주세요");
GridData를 설정해, 친위제트가 되는 Shell의 GridLayout에 대해서 폭전체에 퍼진 배치를 하도록(듯이) 하고 있습니다.
■메뉴의 작성
MenuBar를 Shell로 설정해, 그 아이 요소로서 이하의 부모와 자식 관계를 가지는 메뉴를 작성합니다.
MenuBar +
+ MenuItem( 「파일」) +
+ Menu +
+ MenuItem( 「연다」)
+ MenuItem(단락)
+ MenuItem( 「종료」)
// 메뉴의 작성
Menu menubar = new Menu(shell, SWT.BAR);
shell.setMenuBar(menubar);
MenuItem mItemFile = new MenuItem(menubar, SWT.CASCADE);
mItemFile.setText("파일(&F)");
Menu menuFile = new Menu(mItemFile);
mItemFile.setMenu(menuFile);
mItemOpen = new MenuItem(menuFile, SWT.PUSH);
mItemOpen.setText("연다(&O)");
new MenuItem(menuFile, SWT.SEPARATOR);
MenuItem mItemExit = new MenuItem(menuFile, SWT.PUSH);
mItemExit.setText("종료(&X)");
MenuItem([파일])에는, 아이 요소로서 메뉴를 갖게하기 위한 CASCADE를 지정합니다.MenuItem([연다]), MenuItem([종료])는, 선택했을 때에 이벤트를 발생시키기 위한 PUSH를 지정합니다.
여기까지의 원시 파일은여기(으)로부터 입수할 수 있습니다(파일명, 클래스명을 바꾸고 있습니다).
Eclipse상의 메뉴로부터[실행]->」전회의 기동을[실행]을 선택(또는 키보드로부터[Ctrl + F11]를 입력)하면, 이하와 같은 윈도우가 표시됩니다.
필요한 위제트가 배치되어 어플리케이션다워졌습니다.윈도우의 사이즈를 변경해, GridData가 기대 대로의 레이아웃을 실시할지 확인해 주세요.
그러나, 여기까지의 CSVViewer에서는[여는]이나[종료]메뉴를 선택해도 아무것도 일어나지 않습니다.CSVViewer의 타이틀 바상의[×]버튼을 클릭해, 종료해 주세요.
■CSV 읽어들여, 표시 처리의 실장
다음의 CSVViewer에서는, 「(5) 처리를 실행할 필요가 있는 위제트에 청취자를 등록」을 실장해, 메뉴를 선택했을 때의 처리를 추가해 갈 것입니다.우선은 처리의 실장으로부터 실시합니다.
계속해, 수정 개소 마다 설명해 갈 것입니다.
■인스턴스 변수의 추가
// 파일 다이얼로그용의 필터 확장자(extension)
private final String[] EXTENSIONS = { "*.csv", "*" };
// 읽어들이는 파일명
private String fileName;
// 읽기 시간 측정용
private long beginTime;
CSV 파일명을 대입하는 fileName와 파일 다이얼로그를 사용할 때의 필터 확장자(extension)의 EXTENSIONS, 읽기 시간 측정을 위한 beginTime를 선언합니다.
■테이블의 작성부를 메소드화
메뉴를 호출했을 때에도 테이블을 재작성하는 처리를 실시하기 위해, 테이블의 작성부를 메소드로서 추출해, 코드의 중복을 막습니다.
open 메소드내의 해당 개소를 드러그 해 선택해, Eclipse의 메뉴로부터[리파크타링]->[메소드 의 추출]을 선택합니다.메소드명에 「createTable」라고 입력해,[OK]를 클릭합니다.
public Shell open(Display display) {
...【생략】
//테이블의 작성
createTable(comp);
...【생략】
shell.open();
return shell;
}
private void createTable(Composite parent) {
table = new Table(comp,
SWT.MULTI | SWT.FULL_SELECTION | SWT.BORDER);
GridData tableGrid = new GridData();
tableGrid.horizontalAlignment = GridData.FILL;
tableGrid.verticalAlignment = GridData.FILL;
tableGrid.grabExcessHorizontalSpace = true;
tableGrid.grabExcessVerticalSpace = true;
table.setLayoutData(tableGrid);
// 선을 표시한다
table.setLinesVisible(true);
// 헤더를 가시로 한다
table.setHeaderVisible(true);
// 열의 헤더의 설정
TableColumn col = new TableColumn(table, SWT.LEFT);
col.setText("열 1");
col.setWidth(50);
}
■파일명의 취득 처리의 실장
파일 다이얼로그를 열어, 파일명을 입수하는 처리를 실장합니다.
private void getOpenFileName() {
FileDialog openDialog = new FileDialog(shell, SWT.OPEN);
openDialog.setFilterExtensions(EXTENSIONS);
fileName = openDialog.open();
}
■CSV 파일 읽기전의 처리의 실장
파일명을 취득 후, 실제로 읽어들여 처리에 들어가기 전의 처리를 실장합니다.
private void loadBegin() {
//[여는]메뉴를 선택 불가로 한다
mItemOpen.setEnabled(false);
// 텍스트 박스에 파일명을 설정
textBox.setText(fileName);
// 컬럼수가 바뀌므로, 테이블을 재작성한다
Composite comp = table.getParent();
table.dispose();
createTable(comp);
comp.layout();
// 상태 바에 상태를 표시
statusBar.setText("읽기중...");
// 읽기 시간 측정용
beginTime = System.currentTimeMillis();
}
파일 읽기중은, 새롭게 파일의 읽기를 시작할 수 없게,[여는]메뉴를 선택 불가로 합니다.
SWT의 테이블에서는, 한 번 설정한 컬럼은 파기할 수 없습니다.그 때문에, 테이블 자체를 재작성합니다.테이블의 재작성에는, 방금전 추출한 createTable 메소드를 호출합니다.
텍스트 박스와 상태 바의 표시를 바꾸어 읽기 시간 측정용에 현재의 시간을 System.currentTimeMillis 메소드로 취득합니다.
■CSV 파일 읽기 처리의 실장
파일명이 존재했을 경우, 콤마 단락으로 데이터를 읽어들여, 테이블에 세트 해 갈 것입니다.
private void loadFile() {
BufferedReader reader = null;
try {
File file = new File(fileName);
if (!file.exists()) {
return;
}
// 파일을 연다
reader = new BufferedReader(new FileReader(file));
// 1행 마다 처리를 실시한다
String line = null;
while ((line = reader.readLine()) != null) {
// 콤마로 문자열을 단락짓는다
String[] datas = line.split(",");
// 열이 적으면 더한다
for (int i = table.getColumnCount();
i < datas.length; i++) {
TableColumn column = new TableColumn(table, SWT.LEFT);
column.setText("열" + (i + 1));
column.setWidth(50);
}
// 행을 설정
TableItem item = new TableItem(table, SWT.NULL);
item.setText(datas);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
// 아무것도 하지 않는다
}
}
}
}
BufferedReader를 사용해 1행 마다 파일로부터 읽어들입니다.콤마로 단락짓는 처리는 JDK1.4로부터 사용할 수 있는 split 메소드를 사용하고 있습니다.
또, 현재 테이블이 가지는 렬수보다 읽어들인 데이터의 렬수가 많았던 경우, 차분을 컬럼으로서 추가하고 있습니다.
테이블에의 데이터의 추가는, TableItem 오브젝트를 생성하는 것으로 실현될 수 있습니다.TableItem 오브젝트의 setText 메소드를 사용해, 읽어들인 값을 설정합니다.
마지막에 finally구로, BufferedReader를 close 합니다.
■CSV 파일 읽기 후의 처리의 실장
파일 읽기 후의 처리를 실장합니다.
private void loadEnd() {
mItemOpen.setEnabled(true);
long end = System.currentTimeMillis();
statusBar.setText("독입완료 : 처리 시간"
+ (end - beginTime) + "밀리 세컨드");
}
사전 처리로 실시한,[여는]메뉴의 무효화를 해제합니다.또, 상태 바에, 읽기 처리에 걸린 시간을 밀리 세컨드로 표시합니다.
■종료 처리의 실장
[종료]메뉴 실행시에 불려 가는 종료 처리를 실장합니다.
private void close() {
shell.close();
shell.dispose();
}
■선택행의 표시 처리의 실장
테이블내의 행을 선택했을 때에, 행 번호를 상태 바에 표시하기 위한 처리를 실장합니다.
private void setTableSelectedIndex() {
int index = table.getSelectionIndex();
statusBar.setText(index + "행 눈");
}
이상으로 필요한 처리를 실장할 수 있었습니다.
위제트에의 이벤트 청취자의 등록 처리의 추가
계속 되고, 위제트에의 이벤트에 대해, 논리를 호출하는 청취자를 등록합니다.
■메뉴에의 등록
open 메소드로 메뉴를 작성한 직후에, 각 메뉴에 대해서 호출해야 할 처리를 등록합니다.
// 여는 메뉴
mItemOpen.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
// 파일 다이얼로그를 열어, 파일명을 입수
getOpenFileName();
if (fileName != null) {
// CSV 파일 읽기 사전 처리
loadBegin();
// CSV 파일 읽기 처리
loadFile();
// CSV 파일 읽기 사후 처리
loadEnd();
}
}
});
//종료 메뉴
mItemExit.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
close();
}
});
메뉴에의 처리의 등록은, 각 메뉴에 대해 addSelectionListener 메소드를 사용해 청취자를 추가하는 것으로 실현될 수 있습니다.
SelectionAdapter 클래스는, 메뉴가 가지는 addSelectionListener 메소드의 인수 ISelection 인터페이스를 하늘 실장하는 클래스입니다.SelectionAdapter의 widgetSelected 메소드를, 무명 클래스를 이용해 오버라이드(override) 하는 것으로, ISelection 인터페이스의 모든 메소드를 실장 하지 않아도 돼집니다.
■테이블 선택시의 처리의 추가
createTable 메소드내에서, 테이블에 대해, 메뉴와 같게 청취자를 등록합니다.
table.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
// 테이블 선택시에, 행 번호를 상태 바에 표시
setTableSelectedIndex();
}
});
여기까지의 원시 파일은여기로부터 입수할 수 있습니다.(파일명, 클래스명을 바꾸고 있습니다)
이상의 코딩을 종료하면, 프로그램을 실행해 보세요.적당한 CSV 파일을 준비해, 읽어들여 봅시다.
이것으로 CSVViewer의 기능으로서는 일단 완성입니다.여기까지의 소스는,여기(으)로부터 다운로드해 주세요.
그러나, 실은 이 어플리케이션에는 문제가 있습니다.그것은, 행수가 많은 CSV 파일을 읽어들였을 때에, 파일 읽기중은 어플리케이션이 정지해 버린다고 하는 문제입니다.읽기 상황을 모르면 함께, 윈도우의 이동이나 최소화등이 실시할 수 없게 되어 버립니다.
다음에서는, 이 문제를 해결할 수 있도록 , 어플리케이션의 수정을 실시합니다.
별스렛드로부터의 호출
■왜 정지해 버리는 것인가?
정확하게는, 어플리케이션은 정지하고 있는 것은 아닙니다.loadFile 메소드 실행중에, GUI에의 변경을 묘화 하는 처리가 불려 가지 않게 되기 위해, 재묘화나 윈도우 상태 변화(이벤트)등에의 처리가 늦어 버리는 것이 원인입니다.
main 메소드내의 루프로 Display 오브젝트의 readAndDispatch 메소드를 호출하고 있습니다만, 실은 이 메소드를 호출하는 것으로 묘화나 이벤트의 처리를 합니다.SWT에서는 Display 오브젝트를 생성해, 루프내에서 readAndDispatch 메소드를 실행하는 스렛드를 UI스렛드라고 부릅니다.
이 UI스렛드가 장시간 걸리는 처리를 호출하면, 어플리케이션이 정지하고 있는 것처럼 보여 버립니다.
(클릭하면 확대합니다)
거기서 이 상황을 해결하기 위해서, 별스렛드상에서 파일의 읽기 처리를 실시하게 하도록(듯이) 수정합니다.
(클릭하면 확대합니다)
스렛드화한다
■Runnable를 실장하는 클래스의 작성
별스렛드로 읽어들여 처리를 행하기 위한, Runnable를 실장하는 클래스를 작성합니다.
읽기 처리에서는, CSVViewer가 인스턴스 변수로서 가지는 위제트를 다수 참조할 필요가 있습니다.Runnable를 실장하는 클래스를 CSVViewer와는 다른 원시 파일로서 작성할 수도 있습니다만, 이번은 프로그램을 간단하고 쉽게 하기 위해서, CSVViewer의 이너 클래스로서 작성합니다.
class CSVLoader implements Runnable {
public void run() {
}
}
■[여는]메뉴의 처리의 변경
loadBegin, loadFile, loadEnd를 호출하고 있던 부분을, 별스렛드를 생성해 실행하도록(듯이) 변경합니다.
// 여는 메뉴
mItemOpen.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
// 파일 다이얼로그를 열어, 파일명을 입수
getOpenFileName();
if (fileName != null) {
// 별스렛드로 실행
new Thread(new CSVLoader()).start();
}
}
});
■메소드, 필드의 이동
loadBegin, loadFile, loadEnd 메소드를 CSVLoader로 이동합니다.또, 이러한 메소드로부터 마셔 사용하는 인스턴스 변수 beginTime도 CSVLoader로 이동합니다.그리고, run 메소드내에서 이러한 메소드를 호출하도록(듯이) 합니다.
CSVLoader 부분의 코드는, 이하와 같이 됩니다.
class CSVLoader implements Runnable {
// 읽기 시간 측정용
private long beginTime;
public void run() {
// CSV 파일 읽기 사전 처리
loadBegin();
// CSV 파일 읽기 처리
loadFile();
// CSV 파일 읽기 사후 처리
loadEnd();
}
private void loadBegin() {
// 여는 메뉴를 선택 불가로 한다
mItemOpen.setEnabled(false);
...【생략】
}
private void loadFile() {
...【생략】
}
private void loadEnd() {
...【생략】
}
}
이상으로 파일의 읽기 처리를 별스렛드에 위양 하는 코드가 되었습니다.
■스렛드화의 문제
그런데, 이 상태로 프로그램을 실행하면, 어떻게 될까요.실은,[여는]메뉴를 선택 불가로 하는 (곳)중에, 이하와 같은 SWTException가 발생합니다.
org.eclipse.swt.SWTException: Invalid thread access
at org.eclipse.swt.SWT.error(SWT.java:2330)
at org.eclipse.swt.SWT.error(SWT.java:2260)
at org.eclipse.swt.widgets.Widget.error(Widget.java:385)
at org.eclipse.swt.widgets.Widget.checkWidget(Widget.java:315)
at org.eclipse.swt.widgets.MenuItem.setEnabled(MenuItem.java:557)
at csvviewer.CSVViewer$CSVLoader.loadBegin(CSVViewer.java:173)
at csvviewer.CSVViewer$CSVLoader.run(CSVViewer.java:164)
at java.lang.Thread.run(Thread.java:534)
이 예외는, SWT의 위제트를 조작하는 처리가, 상기로 말한 UI스렛드 이외로부터 실행되었기 때문에 발생합니다(UI스렛드에게만 실행이 용서되고 있다).SWT에서는 이러한 제한을 마련하는 것에 의해서, 복수 스렛드로부터의 GUI 조작에 대해서 심플하고 한편 안전한 동작을 제공하고 있습니다.상세한 것에 대하여는, Eclipse의 헬프의[Platform 플러그 인·디벨로퍼·가이드]->[프로그라마즈·가이드]->[Standard Widget Toolkit]->[스렛드화의 문제]를 참조해 주세요.
SWT에서는, 이와 같이 별스렛드로부터 SWT의 위제트를 조작할 경우에는, Display 클래스의 syncExec, asyncExec 메소드를 사용하고, UI스렛드에 처리를 위양 합니다.
(클릭하면 확대합니다)
구조를 이해할 수 있었더니, 코드를 수정해 나갑시다.
UI스렛드에의 위양
■asyncExec 메소드의 추가
수정 대상은, loadBegin, loadFile, loadEnd 메소드가 됩니다만, 우선은 유틸리티 메소드를 추가합니다.multi-thread 환경하에서 display가 파기되는 일도 고려해(예를 들면 처리중에 윈도우가 닫혀졌다는 등), 이하의 유틸리티 메소드를 CVSLoader에 추가합니다.
private boolean checkAsyncExec(Runnable r) {
if (!display.isDisposed()) {
display.asyncExec(r);
return true;
} else {
return false;
}
}
■loadBegin 메소드의 수정
SWT의 위제트를 조작하는 곳을, checkAsyncExec 메소드를 사용해 UI스렛드에 실행시키도록(듯이) 수정합니다.
private void loadBegin() {
checkAsyncExec(new Runnable() {
public void run() {
//[ 여는] 메뉴를 선택 불가로 한다
mItemOpen.setEnabled(false);
// 텍스트 박스에 파일명을 설정
textBox.setText(fileName);
// 컬럼수가 바뀌므로, 테이블을 재작성한다
Composite comp = table.getParent();
table.dispose();
createTable(comp);
comp.layout();
// 상태 바에 상태를 표시
statusBar.setText("읽기중...");
}
});
// 읽기 시간 측정용
beginTime = System.currentTimeMillis();
}
■loadFile 메소드의 수정
loadBegin와 같게, checkAsyncExec 메소드를 사용합니다.while 루프안만, 이하에 코드를 나타냅니다.
private void loadFile() {
···【생략】
while ((line = reader.readLine()) != null) {
// 콤마로 문자열을 단락짓는다
final String[] datas = line.split(",");
boolean isOK = checkAsyncExec(new Runnable() {
public void run() {
if (table.isDisposed()) {
return;
}
// 열이 적으면 더한다
for (int i = table.getColumnCount();
i < datas.length;
i++) {
TableColumn column =
new TableColumn(table, SWT.LEFT);
column.setText("열" + (i + 1));
column.setWidth(50);
}
// 행을 설정
TableItem item = new TableItem(table, SWT.NULL);
item.setText(datas);
}
});
if (!isOK) {
return;
}
}
···【생략】
}
Runnable의 run 메소드내에서 loadFile 메소드의 로컬 변수 datas를 참조하기 위해(때문에), datas를 final 선언하고 있습니다.또, display, table의 어느 쪽인지가 파기되고 있었을 경우에는 처리를 계속해도 무의미해서, 메소드를 빠지도록(듯이) 하고 있습니다.
■loadEnd 메소드의 수정
loadBegin 메소드와 같게, checkAsyncExec 메소드를 사용합니다.
private void loadEnd() {
checkAsyncExec(new Runnable() {
public void run() {
if (mItemOpen.isDisposed() || statusBar.isDisposed()) {
return;
}
mItemOpen.setEnabled(true);
long end = System.currentTimeMillis();
statusBar.setText(
"독입완료 : 처리 시간"
+ (end - beginTime) + "밀리 세컨드");
}
});
}
메뉴, 상태 바가 파기되고 있었을 경우에는, 처리를 계속되지 않기 때문에 메소드를 빠지도록(듯이) 하고 있습니다.
이상으로 완성입니다.여기까지의 원시 파일은여기(으)로부터 입수할 수 있습니다(파일명, 클래스명을 바꾸고 있습니다).
CSVViewer를 실행해, CSV 파일의 읽기중에, 테이블의 스크롤 바의 이동, 윈도우의 최소화나 이동을 실시해도 어플리케이션이 재빠르게 응답하는 것을 확인해 주세요.
그런데, 여기까지의 CSVViewer에서는 어플리케이션의 응답 속도는 향상했습니다만, 그 반면, 파일의 읽기에 의해 시간이 걸리게 되어 있습니다.CSVViewer의 마지막 수정으로서 튜닝을 실시합니다.
튜닝
■현상 파악
읽어들이는 파일의 크기나, 디스크나 CPU등의 실행 환경의 성능에도 따릅니다만, 필자의 환경에서는 1만행의 레코드를 읽어들이는데, 스렛드화하지 않은 것으로 7.0초, 스렛드화한 것으로 11.7초로 스렛드화에 의해서 약 1.7배의 시간이 걸려 있습니다.
asyncExec 메소드 1회의 호출에 대해, 실행 오브젝트의 생성, Display내의 큐에의 쌓아 올려를 합니다.그리고 UI스렛드에 의한 실행 오브젝트의 큐로부터의 취득, 실행을 합니다.그 사이에는, OS로부터의 이벤트의 감시등도 행해집니다.
당연 이러한 처리에 대한 오버헤드가 존재합니다.그리고 호출해 회수가 많아지면, 그 오버헤드를 무시할 수 없는 크기가 되어 버립니다.
통상, 이러한 호출 회수에 관한 문제는, 버퍼링에 의해 호출 회수를 줄이는 것으로 대응할 수 있습니다.거기서, 파일로부터의 읽기 1행 마다 호출하고 있는 asyncExec 메소드를, 100행 마다 호출하도록(듯이) 수정합니다.
(클릭하면 확대합니다)
■loadFile 메소드의 수정
ArrayList에 읽어들인 데이터를 일시적으로 격납해 두는 것으로, 버퍼링을 실현합니다.
private void loadFile() {
···【생략】
// 버퍼 사이즈
int bufferSize = 100;
while ((line = reader.readLine()) != null) {
final ArrayList array = new ArrayList(bufferSize);
// 콤마로 문자열을 단락짓는다
String[] datas = line.split(",");
array.add(datas);
// 버퍼 사이즈까지 읽어들여
for (int i = 1;
i < bufferSize && (line = reader.readLine()) != null;
i++) {
datas = line.split(",");
array.add(datas);
}
boolean isOK = checkAsyncExec(new Runnable() {
public void run() {
if (table.isDisposed()) {
return;
}
for (int i = 0; i < array.size(); i++) {
String[] datas = (String[]) array.get(i);
// 열이 적으면 더한다
for (int j = table.getColumnCount();
j < datas.length;
j++) {
TableColumn column =
new TableColumn(table, SWT.LEFT);
column.setText("열" + (j + 1));
column.setWidth(50);
}
// 행을 설정
TableItem item = new TableItem(table, SWT.NULL);
item.setText(datas);
}
}
});
if (!isOK) {
break;
}
}
···【생략】
}
완성한 원시 파일은여기(으)로부터 입수할 수 있습니다(파일명, 클래스명을 바꾸고 있습니다).
실행해 효과를 확인했는데, 필자의 환경에서는 7.9초와 스렛드화와 튜닝을 베풀지 않은 것과 비교해서 약 1.1배까지 오버헤드를 줄일 수 있었습니다.
이 튜닝의 주의점으로서는, asyncExec 메소드에 위양 하는 처리 중(안)에서 장시간 걸리는 처리를 실행해 버리면, 전절로 작성한 CSVViewer와 같이 UI스렛드가 점유 되어 버리는 것입니다.최적인 버퍼 사이즈에 대해서는 환경에 의존하고, 또 이번 기사의 취지에서는 빗나가기 때문에, CSVViewer는 이것으로 완성으로 합니다.
정리
본고에서는, SWT에 대한 해설과 Eclipse를 이용한 SWT 어플리케이션의 작성 방법을 소개했습니다.또, SWT 어플리케이션으로 UI스렛드와는 다른 스렛드를 사용하는 방법과 SWT의 중요한 구조인 asyncExec 메소드에 특화한 간단한 튜닝도 실시했습니다.
SWT를 사용하면, GUI의 컴퍼넌트를 조합하고, 고도의 어플리케이션을 간단하게 작성할 수 있습니다.그것은, Eclipse가 SWT로 기술되고 있는 것부터도 알아 받을 수 있다고 생각합니다.
본고가 참고가 되어, 쾌적한 클라이언트 어플리케이션이나 Eclipse 플러그 인을 구축하기 위한 계기가 되면 다행입니다.
다음 번의 기사에서는, 이번 SWT의 내용을 근거로 해 Eclipse의 플러그 인을 개발합니다.기대하세요. 참고:컴퍼넌트 레퍼런스
■쉘
어플리케이션의 큰 범위가 되는 윈도우입니다.SWT에서는, 이 윈도우를 쉘이라고 부릅니다.
컴퍼넌트 설명 Swing에의 대응
Shell 타이틀 바나 최소화/최대화/닫는 버튼을 갖게하는 윈도우.위짓트는, 이 윈도우내에 배치한다 JFrame
■입력·표시계
문자열의 입출력이나, 이벤트의 발생등을 실시할 수 있습니다.
컴퍼넌트 설명 Swing에의 대응
Button 통상의 버튼, 체크 버튼, 라디오 버튼, 토글버튼으로서 사용 JButton
JCheckBox
JRadioButton
JToggleButton
Text 텍스트 입력이 가능한 박스. 단일행/복수행, 스크롤 바의 유무등을 지정할 수 있다 JTextField
JTextArea
Combo 텍스트 박스와 드롭 다운이 짜 합쳐진, combobox.텍스트 박스는 손입력을 금지(Read Only)할 수도 있다 JComboBox
Slider 수치를 조절하기 위해(때문에), 다른 위제트와 동기 해 스크롤 하는 바 JSlider
■표시계
문자열이나 화상의 표시, 일람이나 트리 등, 다양한 것을 표시할 수 있습니다.
컴퍼넌트 설명 Swing에의 대응
Label 문자나 화상을 표시 JLabel
Canvas 임의의 그래픽스를 묘화 JPanel
List 일람을 표시할 수 있는 일람중에서, 단일행 또는 복수행을 선택하도록(듯이) 지정할 수 있다 JList
Table 2 차원의 겉(표)를 표시할 수 있는 열에는 헤더를 붙일 수도 있다 JTable
Tree 디렉토리 계층 등, 부모와 자식 관계를 가지는 요소를 표시할 수 있다 JTree
ProgressBar 진척을 나타내는 바를 표시할 수 있다 JProgressBar
■메뉴·툴바
윈도우의 상부에, 메뉴나 툴바를 배치할 수 있습니다.
컴퍼넌트 설명 Swing에의 대응
Menu 「파일」이나 「헬프」라는 메뉴를 도구모음상에 표시 JMenu
ToolBar 아이콘이나 문자를 가지는 버튼으로부터 구성되는 툴바를 표시 JToolBar
CoolBar 마우스로 드러그 하는 것으로써 배치를 변경할 수 있는 툴바 없음
■컨테이너계
다른 위제트를 안에 포함할 수 있습니다.
컴퍼넌트 설명 Swing에의 대응
Composite 다른 위제트를 안에 포함할 수 있다 JPanel
Group Composite와 같게 다른 위제트를 안에 포함할 수 있어 한층 더 테두리로 둘러쌀 수 있다 JPanel + Border
TabFolder 탭에 의해 페이지를 바꿀 수 있다 JTabbedPane
SashForm 에리어를 2개에 단락짓는다.단락을 마우스로 이동할 수 있다 JSplitPane
■다이얼로그
다음의 6 종류의 다이얼로그를 사용할 수 있습니다.
컴퍼넌트 설명 Swing에의 대응
MessageBox 메세지의 표시를 할 수 있다 JOptionPane
FileDialog 파일의 지정을 실시할 수 있다 JFileChooser
DirectoryDialog 디렉토리의 지정을 실시할 수 있다 JFileChooser
ColorDialog 색 지정을 실시할 수 있다 JFileChooser
FontDialog 폰트의 지정을 실시할 수 있다 없음
PrintDialog 프린터의 지정을 실시할 수 있다 Java Print API의 PrinterJob
이하는 눈에 보이는 위제트가 아닙니다만, 어플리케이션을 구축하는데 필요한 것입니다.
■레이아웃 매니저
레이아웃을 지정해, 컨테이너계 위제트내의 배치를 조정할 수 있습니다.
컴퍼넌트 설명 Swing에의 대응
FillLayout 빈틈을 채워 수평 또는 수직에 위제트를 배치한다 BoxLayout
FormLayout 다른 위제트의 레이아웃을 참조해 배치할 수 있다.예를 들면 「위제트 A의 하단으로부터 n픽셀 떨어져 위제트 B를 둔다」라고 한 지정을 할 수 있다 SpringLayout
RowLayout 수평 또는 수직에 위제트를 배치합니다.마진이나 위제트간의 스페이스를 지정할 수 있다 BoxLayout
FlowLayout
GridLayout HTML의 table 태그를 닮은 형식에서 배치할 수 있는 owspan나 colspan를 지정할 수 있다 GridBagLayout
StackLayout 톱에 있는 위제트만을 표시하는 레이아웃 CardLayout
주:Swing에서는 Java AWT의 레이아웃 매니저를 사용하기 위해(때문에), java.awt 부하의 클래스도 「Swing에의 대응」으로서 열거하고 있습니다.
■이벤트 리스너-
키 입력이나 위제트의 선택등이 다양한 이벤트에 의해, 기동되는 인터페이스입니다.어플리케이션의 논리는, 청취자를 실장한 클래스를 위제트에 등록하는 것으로, 이벤트 발생시에 불려 갑니다.
컴퍼넌트 설명 Swing에의 대응
SelectionListener 위제트가 선택되었을 때에 기동되어 많은 위제트로 설정할 수 있다 ActionListener
KeyListener 키보드로부터 키 입력되었을 때에 기동된다 KeyListener
FocusListener 위제트가 포커스를 얻거나 잃었을 때에 기동된다 FocusListener
MouseListener 위제트상에서 마우스를 누르거나 놓거나 더블 클릭 했을 때에 기동된다 MouseListener
주:Swing에서는 Java AWT의 청취자를 사용하기 위해(때문에), java.awt.event 부하의 인터페이스도 「Swing에의 대응」으로서 열거하고 있습니다.
또, SWT에서는 각 청취자를 하늘의 처리로 실장하는 아답터 클래스(SelectionAdapter등)를 제공하고 있습니다. 청취자로 규정 떠날 수 있어 모든 메소드를 실장할 필요가 없고, 필요한 메소드만 실장하면 좋기 때문에 편리합니다.
■그 외
컴퍼넌트 설명 Swing에의 대응
Display SWT와 플랫폼과의 사이의 접속을 나타냅니다.어플리케이션의 최초로 작성되어 마지막에 삭제된다 없음
Program 파일의 확장자(extension)에 의해서 관련지을 수 있고 있는 외부의 프로그램을 기동할 수 있다 없음
SWT 위제트를 생성할 경우에 지정하는 스타일을, 정수로서 정의하고 있다 없음
이 포스트를..
덧글 쓰기 엮인글 쓰기
키친에서 등록한 글입니다.
키친에서 수정하시겠습니까?
이 글을 삭제하시겠습니까?
키친에서 등록한 글은 키친에서 삭제해주세요.
키친에서 등록한 글 보기
이 포스트를 삭제하시겠습니까?
작성하신 글은 아래의 서비스로 보내신 글입니다.
삭제시 보낸 곳에서도 자동 삭제됩니다.
글 보내기 정보
‘SWT’ 카테고리의 다른 글
SWT실행 on Eclipse
2007/10/23
Eclipse 플러그 인 개발하기(2/2)
2007/10/23
Eclipse 플러그 인 개발하기(1/2)
2007/10/23
Eclipse를 이용한 SWT 어플리케이션의 작성
2007/10/23
제11회 JVE로 편집할 수 없는 레이아웃을 2개 소개
2007/10/23
1 2 3
'Eclipse' 카테고리의 다른 글
Eclipse Remote System Explorer (RSE) 플러그인 설치 가이드 (4) | 2009.08.02 |
---|---|
이클립스 getter/setter 자동 추가 단축키 (0) | 2009.07.12 |
Eclipse package presentation Hierarchical (1) | 2009.06.28 |
Eclipse 단축키 모음 (1) | 2009.06.09 |
JVM terminated exit code=-1 에러 해결 방법 (1) | 2009.05.20 |