반응형
1 공식 사이트 #

2 소개글 #

[http]The Eclipse Project(http://eclipse.org/projects/index.html)
The Eclipse Project is an open source software development project dedicated to providing a robust, full-featured, commercial-quality, industry platform for the development of highly integrated tools. The mission of the Eclipse Project is to adapt and evolve the eclipse technology to meet the needs of the eclipse tool building community and its users, so that the vision of eclipse as an industry platform is realized.

Eclipse 프로젝트는 견고하고, 상업용 수준의 훌륭한 통합 도구의 개발을 위한 플랫폼을 제공하기 위한 오픈소스 소프트웨어 개발 프로젝트 입니다. Eclipse 프로젝트의 임무는 Eclipse 도구를 필요로 하는 단체와 사용자들이 Eclipse 기술을 접하면서 이를 발전, 이용하도록 도모하는 것입니다. 그렇게, 산업 플렛폼으로서 Eclipse의 비전은 실천되었습니다.

2.1 스크린샷 #


eclipseScreen01.png
위 화면은 사용중인 eclipse 화면입니다(설치 후 기본 화면은 아닙니다^^)

3 Eclipse 에 대하여 #

Eclipse 는 IBM 에서 시작되었고, [http]여러 업체들(http://eclipse.org/org/index.html)이 지원하고 있는 오픈소스 프로젝트입니다. 앞에서 언급한 대로, 특정 언어보다 개발 도구를 위한 플랫폼(Platform) 개발을 목표로 하고 있습니다. 이 목표는 Eclipse의 [http]플러그인(Plugin)(http://eclipse.org/whitepapers/eclipse-overview.pdf) 구조를 통해 현실화됩니다.

3.1 특징 및 주요 기능 #

  • 자바 프로그래밍 개발이 용이하며, 플러그인을 통해 C/C++(CDT 플러그인), [http]PHP(http://sourceforge.net/projects/phpeclipse/), [http]HTML(http://sourceforge.net/projects/phpeclipse/), ASP 등 여러 언어의 개발이 가능합니다.
    • ASP 관련 플러그인은 찾기 힘드네요. 설치해본 적이 있는데, 아시는 분 링크 부탁드립니다 ^^
  • 훌륭한 CVS 클라이언트의 기능을 수행. 강력한 diff 까지 수행합니다.
  • 자바 기반으로 VM 위에서 어떤 플랫폼에서든 실행 가능합니다.
  • 다양한 플러그인을 통한 확장이 가능합니다.
  • 자바에 대해 강력한 리팩토링 기능을 제공합니다.

3.2 요즘은 #


현재(2004-12-30)는 3.0.1 버젼으로 Stable 버젼이 나와있으며, 3.1M4(Unstable) 에서는 ?JDK1.5(Java5 - 타이거) 의 모든 특징을 쓸 수 있습니다.

4 관련 사이트 #

[http]Eclipse 커뮤니티들(http://eclipse.org/community/index.html)



국내 : [http]http://jlab.net

5 설치 #

5.1 Eclipse Platform, SDK 등 설치 #

  • [http]이곳(http://eclipse.org/downloads/index.php)에서 원하는 버전을 다운로드한 후 특정 디렉토리에 압축을 푸는 것으로 설치됩니다. 구동을 위해 자바 가상 머신(JRE)이 필요합니다. Eclipse 구동시 실행위치에서 JRE 디렉토리를 찾고 그곳에 JRE가 위치하지 않는다면 시스템에서 지원하는 기본 JRE를 이용합니다.
  • 버전에 맞는 Language Packs 을 위의 같은 디렉토리에 압축을 풀면 됩니다. 특별한 설정없이 한글로케일이라면 한글로 나옵니다. (번역자님 감사합니다ㅜㅠ)

5.2 플러그인 설치 #

  • 플러그인의 제작자가 Update Manager를 이용한 배포를 제공하면 원격설치 및 관리가 가능합니다. ex) [http]AJDT(http://www.eclipse.org/ajdt/) [http]AspectJ(http://www.eclipse.org/aspectj/)
  • 플러그인들은 보통 features, plugins 라는 폴더가 있는 데 안의 내용을 설치된 디렉토리에 넣는 것만으로 플러그인을 설치할 수 있습니다. 설치 제거는 파일을 삭제하는 것으로 가능합니다.

5.2.1 쓸만한 플러그인 #


  • 플러그인 공식 사이트 : http://www.eclipse.org/community/plugins.html
  • ?EasyExplorer : ?ResourceView 등에서 Window Explorer 를 바로 열 수 있게 해준다.
  • Memory Monitor : eclipse 에서 사용하고 있는 메모리를 보여주고 Garbage Collect 버튼을 제공해준다.

    5.3 CDT설치 #

    • 도움말 -> ?SoftwareUpdate -> Find and Install -> 설치할 새 기능에 대해 검색 -> 새 원격사이트 로 가서 다음 주소[http]http://update.eclipse.org/tools/cdt/releases/new 와 원하는 이름을 넣고 갱신 시키면 Eclipse CDT 가 보입니다. 원하는 버전을 설치하시면 C, C++을 사용하실수 있습니다. by ?Gomdori
  • eclipse_update_cdt.png

    6 Visual Editor Plugin 설치 #


    Eclipse 는 기본적으로 JBuilderNetBeans 처럼 Widget Designer(버튼등을 드래그해서 레이아웃을 구성하는) 기능을 가지고 있지 않습니다. 하지만 앞서 말한 플러그인 기능을 통해 지원됩니다. Visual Editor(이하 VE) Project 를 통해 Eclipse 에서 이 기능을 쓸 수 있습니다.
  • [http]VE Project(http://www.eclipse.org/vep/) 에 가셔서 아래쪽의 Download Page -> Last Release 에 가서 최근 버젼을 따라갑니다. 그러면 Release Build 페이지에서, Requirement 에 보면 VE 를 쓰는데 필요한 다른 플러그인들이 있습니다. 거기서 EMF, GEF 가 필요하다고 적혀있으므로 두 개의 플러그인도 같이 다운받습니다. 즉, VE, EMF, GEF 를 다운 받아서 설치합니다(플러그인 설치는 위에 설명되어 있습니다). 설치하고 나면, Java Perspective 에서의 File -> New 에 Visual Class 가 생깁니다.
  • 사용방법은 다른 툴들의 Designer 와 비슷합니다.
  • eclipseVEScreen01.png
    위 화면은 VE 를 설치 후 Visual Class 를 편집하는 화면입니다.


    7 단축키 #

    [http]단축키 Eclipse SDK 2.0(http://dev.eclipse.org/viewcvs/index.cgi/%7Echeckout%7E/platform-ui-home/accessibility/keys.html)

    개발에 자주 쓰이는 단축키는 아래와 같습니다.

    7.1 이동 단축키 #

    Editor 로 커서 이동 F12 컴파일 중 에러등으로 포커스가 다른데로 갔을 때
    특정 줄번호로 가기 CTRL + L
    다음 문제(오류부분으로 가기) CTRL + .(점) 컴파일 중 에러발생시 오류 부분으로 바로가기
    이전 문제(오류부분으로 가기) CTRL + ,(콤마)
    다음(이전) 편집창으로 이동 CTRL + (Shift) + F6 윈도우에서의 Ctrl+Tab 과 같은 기능
    마지막 편집 위치로 가기 CTRL + Q 다른 이동 단축키를 써서 특정 지역으로 왔을 때 바로 전의 위치로 가기
    해당 구문의 선언문으로 이동 F3 함수나 변수위에 커서가 있을 때 사용가능
    해당 구문의 참조 부분 검색 CTRL + Shift + G 함수나 변수위에 커서가 있을 때 이 함수나 변수를 호출,사용하는 곳 검색

    7.2 찾기 #

    찾기 Ctrl+F
    다음찾기 Ctrl+K
    이전찾기 Ctrl+Shift|K
    Incremental Search Ctrl+J - next:?DownArrow, prev:?UpArrow
    Selection Word Search Ctrl+K, Ctrl+Shift+K(Reverse)
    자바 찾기 Ctrl+H 자바의 클래스, 타입, 함수 이름등으로 찾을 수 있다. 문자열을 찾으려면 File Search 탭을 이용한다.


    7.3 디버깅 단축키 #


    브레이크 포인트 CTRL + Shift + B 현 커서의 위치에 브레이크 포인터 설정/해제
    디버깅 시작 F11
    디버깅 계속 F8
    Step Over F6 한줄씩 실행
    Step Into F5 한줄씩 실행하되 함수일 경우 그 함수 내부로 들어감
    Step out(return) F7 현재 함수를 빠져나온다
    Run to Line CTRL + R 현재 라인까지 실행


    7.4 기타 단축키 #

    저장(JDT) 및 컴파일 CTRL + S 기본 옵션으로 저장과 동시에 컴파일로 설정되어 있습니다
    열려진 모든 파일 저장(JDT) CTRL + Shift + S
    빠른 오류 수정(-Quick Fix) CTRL + 1 Eclipse 가 찾을 수 있는 간단한 문법적인 오류를 해결할 방법을 알려줍니다
    코드에 필요한 패키지 자동 import CTRL + Shift + O 현재 코드를 위해 import 해야할 패키지를 자동으로 import 코드를 넣어줍니다
    주석 처리(제거) CTRL + /(\) 현재 줄 혹은 선택된 구역의 주석으로 만들거나, 주석을 제거
    코드 형식 맞추기 Ctrl+Shift+F

    선택 영역 주석처리 Ctrl+/
    선택 영역 주석풀기 Ctrl+\


    8 실행 옵션 #

    • 초기값은 eclipes/workspace 이하의 프로젝트 명 이나 개인 홈/workspace이하의 프로젝트명 폴더에 보관됩니다.
    • 다른 장소나 메모리카드등에 프로젝트를 보존해야 할경우 다음과 같습니다.
     ./eclipse -data [폴더명] 
    • 자바 가상 머신의 지정
      이클립스 자체내에서 사용하는 가상머신을 명시적으로 지정할수 있습니다. 초기값은 쉘상에 지정한 기본 환경변수에서 불러옵니다. 가끔 자바경로명이 잘못 인식해서 이클립스가 실행이 되지 않는 경우에 이 옵션을 쓰면 실행됩니다.
     ./eclipse -vm [자바 가상머신 폴더명과 가상머신 실행파일명] 
    --darkschutepen님 팁을 가져왔습니다. by Gomdory

    9 Visual Studio 형식의 환경 만들기 #


    eclipse 에서는 다양한 환경 설정을 지원합니다. 다음은 Visual Studio 사용자들이 빠르게 eclipse 에 적응하기 위해 설정하면 좋을 것들입니다. 주로 아래의 것들만 손보면 될 것입니다. 세세한 설정은 자신의 취향에 맞춰서 설정하도록 합니다.

    • Preferences -> WorkBench -> Fonts -> Java Editor Text Font : 에디터에 맞는 폰트를 설정(VisualC++ 6.0 : Fixedsys 12, VisualStudio.NET : 돋움체 10)
    • Preferences -> Java -> Code Formmater : 함수 이름 다음에 중괄호가 다음줄에 오는 것등의 설정
    • Preferences -> Java -> Editor : 각종 색깔 결정(보통 Keyword 색깔을 파란색으로)
    • Preferences -> Debug : Remove terminated launches when a new launch is created 를 체크함.

    10 기타 #


    10.1 추천 기능 #


  • 함수나 클래스 이름에 대고 오른쪽 버튼을 누르면 나오는 Reference 를 통해 이 함수, 클래스가 쓰이는 곳을 찾아줍니다.
  • CVS 기능이 무척 강력합니다. 특히 diff 와 merge 를 무척 쉽게 해줍니다.

    10.2#


  • 3.0 이후 약간 무거워진 UI 를 다음과 같은 방법을 통해 이전의 2.x 대의 가벼운 UI 를 쓸 수 있습니다.
  •  Window -> Preferences -> Appearance -> Current Presentation 을 R21Presentaion 으로 수정 
    반응형

    -- 해외 --
    1. 이클립스 공식 홈페이지

    http://www.eclipse.org


    2. 이클립스 위키

    http://eclipsewiki.swiki.net


    -- 국내 --

    1. okjsp

    http://okjsp.pe.kr


    2. 자바스터디

    http://www.javastudy.co.kr


    3. jlab

    http://jlab.net


    4. 자바지기

    http://javajigi.net


    5. 이클립스 관련 자료와 url 이 정리된 사이트

    http://jini-club.net/phpwiki/index.php/Java/Eclipse


    6. 한국 이클립스 사용자 모임

    http://eclipsians.net

    반응형

    번 호 1  
    ERROR Exception in thread "main" java.lang.NoClassDefFoundError: 파일명
    발생되는 경우 클래스 파일을 찾을 수 없는 경우
    조 언 실행하려는 클래스 파일 이름이 제대로 되어 있는지 확인한다.
    또한, CLASSPATH 설정이 제대로 되어 있는지 확인하며 (도스모드에서 set명령어)
    만약, 되어있지 않다면 설정한다. (CLASSPATH = jdk1.3/jre/lib/rt.jar; 2-1강좌 참조)
     
    번 호 2  
    ERROR cannot resolve symbol
    symbol : class in(에러가 난 부분)
    location : class StackTest(찾으려는 위치)
    발생되는 경우 이해할 수 없는 클래스나 메소드, 변수명이 올경우
    조 언 보통 이 에러는 철자가 틀렸을 경우에 많이 발생한다. 클래스, 메소드, 변수의 철자를 세심히 확인해 본다.
    특히, 철자를 확인할때 대소문자 구분을 확실히 체크한다.(자바는 대소문자를 구별한다.) 그리고 클래스에서 발생할 경우 import를 해주었는지 확인해 봅니다.
     
    번 호 3  
    ERROR non-static variable 변수이름(or method 메소드이름) cannot br referenced from a static context
    발생되는 경우 static 메소드 안에서 static 으로 선언되지 않은 메소드나 변수를 참조(사용)했을 경우.
    특히, 메소드의 경우는 인스턴스를 사용하지 않고 static메소드 내에서 바로 선언한 경우.
    조 언 static 선언자의 사용여부를 살펴보고 static 메소드 안에 static으로 선언되어지지 않은 메소드나 변수가 있느지 확인해본다.
    만약 그런것이 있으면 메소드를 새로 만들어 그쪽에서 선언한다. 단, 인스턴스를 생성해서 불러줘야 한다는 것을 잊지 말아야한다.
     
    번 호 4  
    ERROR valiable 변수명 might not have been initialized
    발생되는 경우 지역변수인 변수명의 변수가 초기화가 되어있지 않았을 경우
    조 언 지역변수(메소드 내에서 선언한 변수)를 초기화 하지 않은채 선언했을 경우 발생한다.
    멤버 필드가 아닌 경우는 반드시 변수 선언시 초기화를 해주어야 한다.
    (멤버 필드는 자바 프로그램 자체에서 자동으로 default값으로 초기화 해준다.)
     
    번 호 5  
    ERROR class 클래스명 is public, should be declared in a file named 클래스명.java
    발생되는 경우 클래스명이 public으로 선언되었는데 파일명과 다를 경우
    조 언 public으로 선언된 클래스가 있다면 반드시 그 클래스명과 파일명이 같아야 한다.
    클래스명과 파일명의 대소문자 및 철자가 같은지 비교해 본다.
    또한, public으로 선언된 클래스가 하나 이상 있는지 찾아본다.(반드시 하나만 있어야한다.)
     
    번 호 6  
    ERROR push(java.lang.object)[메소드(인자로 받을 수 있는 형)] in java.util.Stack(메소드의 클래스) cannot be applied to (int)[잘못 들어간 형]
    발생되는 경우 메소드에서 인자를 받을 때 받을 수 있는 형이 아닌 자료형 또는 클래스형을 사용할 경우
    조 언 사용하는 메소드의 API를 참고하여 어떤 형을 인자로 받을 수 있는지 찾아본다.
    API를 보지 못할 경우는 각 자료형으로 인자를 직접 바꾸어 본다.
     
    번 호 7  
    ERROR java.lang.NoSuchMethodError: main
    Exception in thread "main"
    발생되는 경우 클래스 파일 안에서 main() 메소드를 찾을 수 없는 경우
    조 언 자바 애플릿이 아닌 이상 자바 애플리케이션은 반드시 main() 메소드를 사용해야 합니다.
    main() 메소드를 빼먹지 않았는지 확인해 보십시요. 또한 public static void main(String[] args) 형식으로 씌어졌는지도 확인해 보십시요.
    (main 클래스는 반드시 위와 같은 형식으로 만들어져야 합니다.)
     
    번 호 8  
    ERROR unreported exception java.io.IOException(Exception명); must be caught or declared to be thrown
    발생되는 경우 예외가 발생하는데 예외처리를 해주지 않았을 경우
    조 언 예외를 발생하는 메소드 같은 경우는 반드시 예외처리를 해주어야 합니다.
    예외를 발생하거나 예외처리를 해야하는 메소드는 API를 확인해 보시면 알 수 있습니다.
    그렇지 않다면 컴파일 후 지금처럼 에러가 난 예외를 예외처리해 주시면 됩니다.
    또한, 예외를 처리할 때는 메소드 차원에서 throws 예외명을 이용해서 처리할 수 있고
    try{} catch{} 구문을 이용해서 직접 처리해 주셔도 됩니다.(예외 강좌를 참고하세요.)
    특히, 예외도 클래스이므로 반드시 예외가 들어간 패키지를 import 해주어야 합니다.
     
    번 호 9  
    ERROR Note : Calculator.java(파일명) uses or overrides a deprecated API.
    Note : Recompile with -deprecation for details.
    발생되는 경우 JDK 버전이 높아졌거나 보안등의 기타이유로 사용이 deprecated된 메소드를 사용한 경우
    조 언 이건 예외라기 보다는 경고 입니다.(실행하면 됩니다.^^)
    JDK가 버전이 높아지거나 보안등의 이유에 따라 예전에 만들어졌지만 필요가 없어지거나 대체된 메소드가 생겨났습니다.
    그런 메소드를 deprecated 되었다고 하는데 이것은 API상에 나왔있습니다.
    또한, 컴파일할때 -deprecation 옵션주면 어떤 메소드가 deprecate됐는지 알수있읍니다.
    사용이 중지 됐다고 보기 보다는 사용을 가능하면 하지 않게끔 해주는 거죠.
    대치되었거나 버전 업된 메소드를 사용하시면 됩니다.
     
    번 호 10  
    ERROR MouseEvent(클래스명) should be declared abstract; it does not define mouseDragged(java.awt.event.MouseEvent)[메소드명(메소드가 포함된 클래스)] in MouseEvent(클래스명)
    발생되는 경우 implements한 Interface의 모든 메소드를 구현하지 않아서 발생됨
    조 언 Interface는 모든 메소드가 선언만 되고 구현되지 않은 추상(abstract) 메소드입니다.
    만약 Interface를 implements하려면 implements한 클래스가 Interface에서 선언한 모든 메소드를 구현해 주어야 합니다.
    하나라도 빠질 경우 implements한 클래스도 추상 클래스로 보고 에러가 발생합니다.
    에러에 구현해 주어야할 메소드명이 나오므로 그곳에 쓰여있는 메소드를 구현해 주면 됩니다.
    만약, 그 메소드를 구현해 주었는데 에러가 나면 철자 및 대소문자를 다시 확인해 보십시요.
     
    번 호 11  
    ERROR incompatible types
    found : /null(입력한 자료형)
    required : int(요구하는 자료형)
    발생되는 경우 입력을 했을때 맞지 않는 자료형이나 클래스형을 입력할 경우
    조 언 incompatible 은 '성미가 맞지 않는','모순된' 이라는 뜻을 가진 단어 입니다.
    단어뜻 처럼 입력 경우 required 에 나타난 자료형 및 클래스형을 요구하는데
    found 에서 나타난 자료형 및 클래스형을 써주어서 입력을 하지 못하게 되어서 발생하는 에러입니다.
    found 에 나타난 자료형을 required 에 나타난 자료형으로 변경해 주시면 됩니다.
     
    번 호 12  
    ERROR package java.servlet(패키지명) does not exist
    발생되는 경우 import한 패키지가 존재하지 않을 경우
    조 언 import한 패키지가 존재하지 않을 경우에 발생하는 에러입니다.
    철자와 대소문자를 먼저 확인하고 CLASSPATH 설정을 확인해 보시기 바랍니다.
    또한 그 곳에 패키지가 jar파일로 있는지도 확인해 보셔야 합니다.
    (API에 나와있는 패키지는 rt.jar에 다 있습니다.
    단 javax가 붙거나 다름으로 시작되는 확장 패키지는 설치해 주어야합니다.(javax.swing 제외))
     
    번 호 13  
    ERROR java.lang.NullPointerException
    Exception in thread "main"(메소드) java.lang.NullPointerException
    at java.awt.Container.addImpl(Container.java:341)... [에러가 일어난 부분]
    발생되는 경우 참조하거나 사용한 클래스 또는 자료형이 초기화 되지 않은 경우
    조 언 보통 이것은 awt나 배열 부분에서 자주 발생하는데 초기화를 해주지 않아서 많이 발생합니다.
    자바의 변수들은 기본적으로(자동으로 초기화 되는 멤버필드등을 제외하고) 초기화를 요구합니다.
    에러에 체크된 부분을 검토해 보시고 초기화를 해주십시요.
     
    번 호 14  
    ERROR ';'(빠진 부분) expected
    발생되는 경우 문법상으로 써야할 것을 쓰지 않은 경우 발생합니다.
    조 언 주로 ';'을 안써주시거나 아님 '()'(괄호)를 열기만 하고 닫지 않은 실수를 할 경우 발생합니다.
    대부분 이 에러가 발생한 경우는 에러에 나온것을 소스에 추가해 주시면 됩니다.
     
    번 호 15  
    ERROR unexpected type
    required : value(요구하는 타입)
    found : class(소스상 써준 타입)
    발생되는 경우 써주어야 할 타입이 아닌 잘못된 타입을 써주었을 경우
    조 언 unexpected type 에러를 해석하면 '기대하지 않은 타입'이란 뜻을 가지고 있습니다.
    즉, 원하는 타입(required)이 아닌데 잘못된 타입(found)을 써준 경우 발생합니다.
    에러 체크된 부분의 타입을 required 에서 나타난 타입으로 변경해 주시면 됩니다.
     
    번 호 16  
    ERROR java.lang.ArrayIndexOutOfBoundsException
    at Test.main(Test.java:10)[클래스.메소드(파일명:에러난 위치)]
    Exception in thread "main"(예외가 던져진 메소드)
    발생되는 경우 배열의 범위를 넘어선 값을 넣었을 경우
    조 언 위의 에러는 특이하게 컴파일은 이상없이 되지만 실행을 하면 발생하는 에러입니다.
    배열의 범위를 넘어설 경우에 발생하므로 에러난 위치의 배열의 참조 범위를 확인해보시고
    선언해둔 배열의 범위에 맞게 조정해 주시면 됩니다.
     
    번 호 17  
    ERROR illegal start of expression
    발생되는 경우 선언자(modifier)를 잘못 집어 넣은 경우
    조 언 에러의 단어뜻을 확인해 보면 '표현의 시작이 부적격 합니다.'하고 해석할 수 있습니다.
    보통 선언자가 맞지 않거나 쓰일데가 아닌데 선언자를 줄 경우에 많이 발생합니다.
    특히 메소드안에서 static 선언자를 쓴 경우에는 직격으로 볼수 있죠.
    에러가 난 부분의 선언자를 제거하거나 맞는 것인지 다시 확인해 보십시요.
     
    번 호 18  
    ERROR java.io.InputStream(클래스) is abstract; cannot be instantiated
    발생되는 경우 abstract로 선언된 클래스를 직접 new 명령어를 이용하여 인스턴스화 할 경우
    조 언 abstract로 선언된 클래스를 직접 new 명령어를 이용하여 인스턴스화 할 경우에 발생하는 에러입니다.
    왜냐하면, 추상 클래스는 직접 new 명령어를 이용하여 인스턴스화 할수 없기 때문입니다.(객체를 못만든다구요.)
    이 경우에는 인스턴스를 다른 방법으로 생성하시면 됩니다.
    예를 들어 인스턴스를 반환하는 메소드를 이용한다거나 상속을 통해서 상속받은 클래스의 인스턴스를 만들어
    직접 인스턴스를 만드는 효과를 낼수도 있구요. 원하시는 방법으로 바꾸어 보시길...
     
    번 호 19  
    ERROR local variable name(변수명) is accessed from within inner class; needs to be declared final
    발생되는 경우 Local Class의 변수를 final로 선언하지 않은 경우
    조 언 Local Class의 변수는 참조변수의 참조값 변동을 방지하기 위하여 final 선언자를 붙여주어야 합니다.
    변수에 final 선언자를 붙이면 변수는 값을 변동할 수 없는 상수 처럼 쓰이며
    만약 이 값을 참조할 경우 자바는 이 값을 넘기는게 아니라 이 값의 복사본을 참조 값으로 넘기게 됩니다.
    그러므로 Local Class에서 참조값 변동없이 변수를 참조할 수 있게 되는 것입니다.
    Local Class를 정의해준 곳을 살펴보고 final 선언자를 확실하게 확인하시기 바랍니다.
     
    번 호 20  
    ERROR inner classes cannot have static declarations
    발생되는 경우 내부 클래스 안에서 static 선언자를 쓴 경우
    조 언 내부 클래스 안에서는 static 선언자를 쓸수 없습니다.
    내부 클래스 안에서 사용된 static 선언자를 제거해 주십시요.
     
    번 호 21  
    ERROR referenceto List is ambiguous,both class java.util.List(클래스) in java.util(패키지)
    and class java.awt.List(클래스) in java.awt(패키지) match
    발생되는 경우 클래스 사용시 다른 패키지내에 동일이름의 클래스들이 있어서 참조가 모호할 경우
    조 언 예시를 보면 아시겠지만 import 한 패키지중에 같은 이름을 사용하는 클래스를 클래스 이름만으로
    생성함으로서 참조가 모호해질 경우 발생하는 에러입니다.
    이와 같은 경우는 import를 하나 제거 하거나 아님 java.util.List 이런식으로
    직접 그 클래스의 패키지를 같이 써줌으로서 모호성을 제거할수 있습니다.
     
    번 호 22  
    ERROR m()(메소드명) in B(클래스명) cannot override m()(메소드명) in A(클래스명);
    attempting to use incompatiable return type
    발생되는 경우 클래스를 상속받고서 메소드를 오버라이드 하고자할때 잘못한 경우
    조 언 클래스를 상속받고서 메소드를 오버라이드 할 경우에는 지켜야 하는 규칙이 있습니다.
    1. 메소드의 이름이 같아야 합니다.
    2. 메소드의 파라미터 개수, 데이터형이 같아야 합니다.
    3. 메소드의 리턴형이 같아야 합니다.
    4. 상위 메소드와 동일하거나 더 구체적인 Exception을 발생시켜야 합니다.
    5. 상위 메소드와 동일하거나 접근범위가 더 넣은 접근 제한자를 사용해야 합니다.

    님의 메소드 오버라이드시 위 규칙을 잘 지켰는가를 다시 한번 확인해 보세요.
     
    번 호 23  
    ERROR getPathBetweenRows(int,int)(메소드) has protected access in javax.swing.jTree(클래스)
    발생되는 경우 protected로 선언된 메소드를 상속 없이 직접 불러쓸 경우
    조 언 protected로 선언되어 있는 메소드는 상속하거나 같은 package에 있을 때만 쓸 수 있습니다.
    상속해서 다시 public 메소드로 값을 받던지 아니면
    public 메소드 중에서 비슷한 기능을 하는 메소드가 있는지 찾아서 바꾸어주어야 합니다.
     
    번 호 24  
    ERROR invalid method declaration; return type required
    발생되는 경우 리턴 타입을 쓰지 않아 메소드의 선언이 잘못된 경우
    조 언 리턴 타입을 쓰지 않아 메소드의 선언이 잘못된 경우에 발생하는 에러이므로
    에러가 발생한 메소드를 확인해보고 리턴 타입을 맞게 적어주어야 합니다.
     
    번 호 25  
    ERROR Error occurred during initialization of VM
    java.lang.ExceptionInInitializerError
    발생되는 경우 static으로 선언된 변수중 초기화가 안되어 있는 것이 있는 경우
    조 언 static으로 선언된 변수중에 초기화가 안된게 있는 경우에 발생하는 에러이므로
    에러가 발생한 변수를 확인해보고 알맞은 초기화를 시켜주거나 변수의 위치를
    자동 초기화가 가능한 메소드 밖의 클래스 변수로서 사용하게 합니다.
     
    번 호 26  
    ERROR Error opening registry key 'Software\JavaSoft\Java Runtime Environment'
    Error: could not find java.dll
    Error: could not find Java 2 Runtime Environment
    발생되는 경우 중복설치 등으로 인해 레지스트리 키값이 잘못되어 있는 경우
    조 언 중복설치 등으로 인해 레지스트리 키값이 잘못되어 있는 경우에 발생하는 에러이므로
    레지스트리 편집기를 열어서 HKEY_LOCAL_MACHINE -> SOFTWARE -> JavaSoft에
    보시면 3개의 키가 있을 겁니다. 그중에서 첫번째 키인 Java 런타임 환경 을 마우스
    오른쪽 버튼으로 클릭하여 Java Runtime Environment로 이름을 바꿔주시면 됩니다.
     
    번 호 27  
    ERROR Error Registry Key 'Sofrware\JavaSofrware\Java Runtime Environment\CurrentVerison'
    has value '1.1',but '1.3' is requried.
    Error: could not find java.dll
    Error: could not find java 2 Runtime Enviroment.
    발생되는 경우 중복설치 등으로 인해 레지스트리 키값의 자바 버전이 잘못되어 있는 경우
    조 언 중복설치 등으로 인해 레지스트리 키값의 자바 버전이 잘못되어 있는 경우에 발생하는 에러이므로
    레지스트리 편집기를 열어서 HKEY_LOCAL_MACHINE -> SOFTWARE -> JavaSoft -> Java Runtime Environment의 Current version의 값을 1.3으로 되어있는지 확인해 주시면 됩니다.
     
    번 호 28  
    ERROR java.lang.ClassNotFoundException: org.gjt.mm.mysql.Driver(드라이버명)
    발생되는 경우 JDBC로 데이터 베이스에 연결하는 중 드라이버를 찾지 못할 경우
    조 언 JDBC를 연결하는 중에 드라이버를 찾지 못할 경우에 발생하는 에러이므로
    각 데이터 베이스에 맞는 드라이버가 제대로 다운로드 되었는지 확인해 보시고
    드라이버의 위치가 클래스 패스에 잡혀 있는지 확인해주시면 됩니다.
     
    번 호 29  
    ERROR Method printIn(java.lang.String)(메소드명) not found in class java.io.PrintStream(클래스명)
    발생되는 경우 자신이 사용한 클래스의 메소드가 맞지 않는(=없는)경우
    조 언 자신이 사용한 클래스의 메소드가 맞지 않는(=없는) 경우에 발생하는 에러이므로
    API를 통해서 사용하고자 하는 클래스와 메소드를 다시 한번 확인해 봅니다.
    보통 이경우 메소드의 철자나 대소문자를 잘못 쓴 경우가 많으니 그점을 유심히 살표봅니다.
    마지막으로 철자와 대소문자도 맞는다면 메소드의 인자의 객체형을 맞게 주었는지 확인해보면 됩니다.
     


    반응형
    [JAVA] 배워서 남주기 게시물 [67]건
    제목 주제 작성자 내용 [모두보기] [주제입력]
      [공지]
    1. 입력된 주제에 회원님들은 답변(reply)함으로써 알고 있는 지식을 여러 벗들과 공유하게 됩니다.
      주제입력은 운영자만이 할수 있습니다.
      이점 양해해 주시기 바라며, 필요한 주제가 있으면 게시판에 올려 주십시요.. 감사 합니다.
    1. [주제] File class Example.....[운영자 재공]관련정보 추가[reply]
        드라이브명과 특정 디렉토리안의 파일 출력하기.....[2004-02-09] [studyto님 재공] [조회:190]
        파일 다이얼로그 창을 열어 파일 선택하기.....[2004-02-10] [park님 재공] [조회:143]
        특정디렉토리내의 파일목록보기.....[2004-02-12] [park님 재공] [조회:70]

    2. [주제] Applet 응용 프로그램.....[운영자 재공]관련정보 추가[reply]

    3. [주제] Application 응용 예제.....[운영자 재공]관련정보 추가[reply]
        신상정보 입력후 출력하기.....[2004-02-09] [park님 재공] [조회:163]
        문자열 타이핑효과 및 스크롤효과 주기.....[2003-10-27] [park님 재공] [조회:182]

    4. [주제] 자바 개론및 이해.....[운영자 재공]관련정보 추가[reply]
        내부 클래스(method type).....[2004-02-08] [park님 재공] [조회:98]
        접근 제한자.....[2003-10-21] [park님 재공] [조회:118]
        반복문과 제어문.....[2003-10-21] [park님 재공] [조회:71]
        extends 와 implements.....[2003-10-21] [park님 재공] [조회:74]
        자바 개요.....[2003-10-21] [park님 재공] [조회:84]
        애플리케이션의 첫번째 프로그래.....[2003-10-21] [park님 재공] [조회:69]
        배열 선언.....[2003-10-21] [park님 재공] [조회:161]
        데이터형.....[2003-10-21] [parksj님 재공] [조회:63]
        다차원 배열.....[2003-10-21] [parksh님 재공] [조회:65]
        Linux에서 자바 환경 설정하기.....[2003-11-24] [park님 재공] [조회:70]

    5. [주제] 네트워크 제어하기.....[운영자 재공]관련정보 추가[reply]
        InetAddress를 사용하여 IP주소 알아내기.....[2003-10-22] [park님 재공] [조회:26]
        URL 클래스.....[2003-10-23] [park님 재공] [조회:21]

    6. [주제] 이미지처리와 오디오 처리.....[운영자 재공]관련정보 추가[reply]

    7. [주제] 입출력 스트림 제어하기.....[운영자 재공]관련정보 추가[reply]
        한문자 입력후 출력하기.....[2004-02-09] [studyto님 재공] [조회:107]
        한줄 입력 받아 출력하기(한글 정상적 처리).....[2004-02-09] [studyto님 재공] [조회:139]
        입력받은 문자열 파일로 저장하기.....[2004-02-10] [park님 재공] [조회:177]
        파일 스트림을 사용하여 텍스트파일 모두 읽어 들이기.....[2004-02-10] [park님 재공] [조회:130]

    8. [주제] 예외처리와 쓰레드 처리.....[운영자 재공]관련정보 추가[reply]
        쓰레드.....[2003-10-21] [park님 재공] [조회:26]
        예외처리.....[2003-10-21] [park님 재공] [조회:29]

    9. [주제] 그래픽 처리.....[운영자 재공]관련정보 추가[reply]
        마우스를 사용하여 선그리기.....[2004-04-14] [park님 재공] [조회:76]
        마우스를 사용하여 사각형 그리기.....[2004-04-14] [park님 재공] [조회:66]
        마우스로 사각형 그리고 reDraw하기.....[2004-04-14] [park님 재공] [조회:59]
        도형 그리기와 메뉴.....[2004-04-16] [park님 재공] [조회:75]
        그래픽 멤소드.....[2003-10-21] [park님 재공] [조회:38]

    10. [주제] 이벤트종류와 이에 대한 사용법.....[운영자 재공]관련정보 추가[reply]
        MouseMotionListener Sample(마우스 현재 좌표값 출력).....[2004-04-02] [park님 재공] [조회:13]
        이벤트의 종류.....[2003-10-21] [park님 재공] [조회:16]

    11. [주제] AWT 컴포넌트와 Layout관리자 사용하기.....[운영자 재공]관련정보 추가[reply]
        제목표시줄 없는 창 만들기.....[2004-04-08] [park님 재공] [조회:29]
        현재 시스템의 폰트 목록 가져오기.....[2004-11-06] [studyto님 재공] [조회:24]
        Frame에서 Dialog Box 띄우기.....[2003-10-21] [park님 재공] [조회:37]
        Layout 관리자.....[2003-10-21] [park님 재공] [조회:32]
        AWT 컴포넌트.....[2003-10-23] [park님 재공] [조회:38]

    12. [주제] Swing 콤포넌트 제어하기.....[운영자 재공]관련정보 추가[reply]
        JTree.....[2005-02-01] [park님 재공] [조회:18]
        현재 윈도우의 전체 크기에 맞게 프레임 만들기.....[2005-02-13] [studyto님 재공] [조회:26]
        파일 필터링하기(FIleFilter).....[2005-02-25] [park님 재공] [조회:18]
        JScrollPane 스크롤바 자동으로 맨 아래로 이동 시키기.....[2005-03-02] [studyto님 재공] [조회:24]

    13. [주제] JDBC 사용하기.....[운영자 재공]관련정보 추가[reply]
        Record Select.....[2004-04-27] [park님 재공] [조회:61]
        테이블의 필드명 알아내기.....[2005-03-04] [studyto님 재공] [조회:65]

    14. [주제] Applet에서 DB Access하기.....[운영자 재공]관련정보 추가[reply]
        Applet에서 DB연결.....[2003-10-21] [park님 재공] [조회:30]

    15. [주제] 문자열 함수.....[운영자 재공]관련정보 추가[reply]

    16. [주제] Socket 사용하기.....[운영자 재공]관련정보 추가[reply]
        소켓을 활용한 실시간 메시지 전달 서비스.....[2003-12-03] [park님 재공] [조회:49]
        소켓을 사용한 간단한 채팅.....[2003-12-05] [park님 재공] [조회:48]
        클라이언트의 현재 마우스 좌표 송출(서버).....[2004-04-07] [park님 재공] [조회:28]
        클라이언트의 현재 마우스 좌표 송출(클라이언트).....[2004-04-07] [park님 재공] [조회:29]
        가장 간단한 소켓 서버와 클라이언트.....[2003-11-27] [park님 재공] [조회:42]

    17. vector 사용하기.....[운영자 재공]관련정보 추가[reply]

    18. (Tip)자바에서 함수는 어떤 방법으로 호출하나.....[운영자 재공]관련정보 추가[reply]

    19. 메뉴만들기.....[운영자 재공]관련정보 추가[reply]
        메뉴바 만들기(하위메뉴 포함).....[2004-04-14] [park님 재공] [조회:69]
    반응형

    1 메뉴 사용하기


    자바 Swing 에서 메뉴를 사용하기 위해서는 3개의 클래스가 필요하다


    javax.swing.JMenu 클래스

    javax.swing.JMenuBar 클래스

    javax.swing.JMenuItem 클래스


    JMenuBar 클래스는 JMenu 를 담아두는 클래스로 꼭 한개 필요하다

    JMenu 클래스는 JMenuBar 에 추가되어 각종 메뉴를 구성하는데

    예를 들자면 지금 사용하고 있는 Explorer 의 파일(F) 편집(E) 등등이 각각 하나의 메뉴이다

    JMenuItem 은 메뉴에 추가되어 사용되는 클래스로 Explorer 의 파일(F) 메뉴 내의

    새로 만들기, 열기 등등을 지칭한다..


    사용법은 JMenuBar 를 생성하고 여기에 add() 메소드로 각각 생성된 JMenu 를 더하고

    JMenu 의 add() 메소드로 각각의 JMenuItem 클래스를 더하면 된다.

    마지막으로 setJMenuBar() 메서드를 통해 JFrame 클래스에 메뉴바를 더하면 된다


    // 각종 필드 선언

        private JMenu jFile;
        private JMenuBar jMenuBar;
        private JMenuItem jOpen;


    // 각종 필드 생성

        jMenuBar = new JMenuBar();
        jFile = new JMenu("File");
        jOpen  = new JMenuItem("Open");


    // 실제 더하기

        jFile.add(jOpen);
        jMenuBar.add(jFile);

        setJMenuBar(jMenuBar);



    이벤트는 메뉴 아이템 객체에 addActionListener(); 메서드를 통해서 주면 된다


    이렇게 말이다..




    2. 파일 다이얼로그 사용하기


    javax.swing.JFileChooser 클래스를 사용하면 된다.


        File file;
       
        JFileChooser fc = new JFileChooser();
        int returnVal = fc.showOpenDialog(this);

        if (returnVal == JFileChooser.APPROVE_OPTION)
        {
                file = fc.getSelectedFile();
        }


    위 소스 처럼 간단이 사용하면 되는데

    선택된 파일 정보는 file 필드내에 저장되어 있다

    궁금하다면 if 내에 System.out.println(file.getName()); 메서드를 확인하면 된다.


    다이얼 로그는 아래 사진처럼 열리게 된다.




    옵션으로 필터도 줄 수 있는데 자세한 사항은 스킵하자


    그럼 위 두개를 사용하여 File 메뉴에 Open 을 클릭하면 파일 다이얼 로그가 열리게

    만든 소스를 만들었다

    제일 위부분 다운 받는 곳에서 다운 받아서 확인하자..

    반응형

    1. Introduction: Custom Models and Renderers


    The idea of custom data models and cell renderers was covered in detail in the Swing tutorial section on JList. JTree is another component that commonly uses these techniques. This section will illustrate the basic use of JTree, show how to respond to node selection events, give an example of a custom model (a tree that builds the children "on the fly") and show how replace the icons that appear at the tree nodes.



    2. Simple JTree


    The simplest and most common way to use JTree is to create objects of type DefaultMutableTreeNode to act as the nodes of the tree. Nodes that have no children will be displayed as leaves. You supply a value, known as the "user object", to the DefaultMutableTreeNode constructor, to act as the value at each node. The toString method of that user object is what is displayed for each node.


    Once you have some nodes, you hook them together in a tree structure via parentNode.add(childNode). Finally, you pass the node to the JTree constructor. Note that, since trees can change size based upon user input (expanding and collapsing nodes), trees are usually placed inside a JScrollPane. For example, here is a very simple tree:


    DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root");
    DefaultMutableTreeNode child1 = new DefaultMutableTreeNode("Child 1");
    root.add(child1);
    DefaultMutableTreeNode child2 = new DefaultMutableTreeNode("Child 2");
    root.add(child2);
    JTree tree = new JTree(root);
    someWindow.add(new JScrollPane(tree));


    For more complicated trees, it is sometimes tedious and hard to maintain if you hook everything together "by hand". So you may find it useful to first make a simple tree-like data structure, then build nodes and hook them together automatically from that data structure. Here's an example that uses nested arrays to define the data structure.


    2.1 Simple JTree Example: Source Code (Download source code)


    import java.awt.*;
    import javax.swing.*;
    import javax.swing.tree.*;

    public class SimpleTree extends JFrame {
      public static void main(String[] args) {
        new SimpleTree();
      }

      public SimpleTree() {
        super("Creating a Simple JTree");
        WindowUtilities.setNativeLookAndFeel();
        addWindowListener(new ExitListener());
        Container content = getContentPane();
        Object[] hierarchy =
          { "javax.swing",
            "javax.swing.border",
            "javax.swing.colorchooser",
            "javax.swing.event",
            "javax.swing.filechooser",
            new Object[] 
    { "javax.swing.plaf",
                           "javax.swing.plaf.basic",
                           "javax.swing.plaf.metal",
                           "javax.swing.plaf.multi" },
            "javax.swing.table",
            new Object[] { "javax.swing.text",
                           new Object[] { "javax.swing.text.html",
                                          "javax.swing.text.html.parser" },
                           "javax.swing.text.rtf" },
            "javax.swing.tree",
            "javax.swing.undo" };
       
    DefaultMutableTreeNode root = processHierarchy(hierarchy);
        JTree tree = new JTree(root);
        content.add(new JScrollPane(tree), BorderLayout.CENTER);
        setSize(275, 300);
        setVisible(true);
      }

      /** Small routine that will make node out of the first entry
       *  in the array, then make nodes out of subsequent entries
       *  and make them child nodes of the first one. The process is
       *  repeated recursively for entries that are arrays.
       */

       
      private DefaultMutableTreeNode processHierarchy(Object[] hierarchy) {
       
    DefaultMutableTreeNode node =
          new DefaultMutableTreeNode(hierarchy[0]);
        DefaultMutableTreeNode child;
        for(int i=1; i<hierarchy.length; i++) {
          Object nodeSpecifier = hierarchy[i];
          if (nodeSpecifier instanceof Object[])  // Ie node with children
            child = processHierarchy((Object[])nodeSpecifier);
          else
            child = new DefaultMutableTreeNode(nodeSpecifier); // Ie Leaf
          node.add(child);
        }
        return(node);
      }
    }


    Note: also requires WindowUtilities.java and ExitListener.java, shown earlier.


    2.2. Simple JTree Example: Initial Result


     

    2.2. Simple JTree Example: Expanded Result
     
     
     
     
    3. Handling JTree Events
     
    To handle selection events, attach a TreeSelectionListener. The TreeSelectionListener interface requires a single method; valueChanged. You extract the currently selected node via tree.getLastSelectedPathComponent, then casting that to your node type (usually DefaultMutableTreeNode), then extracting the user object via getUserObject. However, if all you want is the node label, you can just call toString on the result of tree.getLastSelectedPathComponent. Here's an example:
     
    3.1 JTree with Selectable Nodes: Source Code (Download source code)
     
    import java.awt.*;
    import javax.swing.*;
    import javax.swing.tree.*;
    import javax.swing.event.*;

    public class SelectableTree extends JFrame
                                implements TreeSelectionListener {
      public static void main(String[] args) {
        new SelectableTree();
      }

      private JTree tree;
      private JTextField currentSelectionField;
     
      public SelectableTree() {
        super("JTree Selections");
        WindowUtilities.setNativeLookAndFeel();
        addWindowListener(new ExitListener());
        Container content = getContentPane();
        DefaultMutableTreeNode root =
          new DefaultMutableTreeNode("Root");
        DefaultMutableTreeNode child;
        DefaultMutableTreeNode grandChild;
        for(int childIndex=1; childIndex<4; childIndex++) {
          child = new DefaultMutableTreeNode("Child " + childIndex);
          root.add(child);
          for(int grandChildIndex=1; grandChildIndex<4; grandChildIndex++) {
            grandChild =
              new DefaultMutableTreeNode("Grandchild " + childIndex +
                                         "." + grandChildIndex);
            child.add(grandChild);
          }
        }
        tree = new JTree(root);
        tree.addTreeSelectionListener(this);
        content.add(new JScrollPane(tree), BorderLayout.CENTER);
        currentSelectionField = new JTextField("Current Selection: NONE");
        content.add(currentSelectionField, BorderLayout.SOUTH);
        setSize(250, 275);
        setVisible(true);
      }

     
    public void valueChanged(TreeSelectionEvent event) {
        currentSelectionField.setText
          ("Current Selection: " +
           tree.getLastSelectedPathComponent().toString());
      }
    }
     
    Note: also requires WindowUtilities.java and ExitListener.java, shown earlier.
     
    3.2. Selectable JTree Example: Initial Result
     
     
     
    3.3. Selectable JTree Example: Result after Expanding Tree and Selecting Node
     
     
     
     
    4. Custom Models and Dynamic Trees
     

    A JTree uses a TreeModel to get its data. As with JList, you can replace the model altogether, specifying how to extract data from the custom model. See the tutorial section on JList for an example of this general approach.

     
    In the case of JTree, however, the default TreeModel uses a TreeNode to store data associated with the tree, and it is more common to leave the TreeModel unchanged and instead make a custom TreeNode. The easiest approach for that is to start with DefaultMutableTreeNode. One of the common cases where this is useful is when you don't want to explicitly lay out each node in the tree, but instead you have some sort of algorithm that describes the children of a given node, and you want to build the tree dynamically, only actually generating children for places that the user expands. For instance, in the following example the tree is potentially infinite, with each node describing a section in an outline. The root will be "1", the first-level children will be 1.1, 1.2, 1.3, etc., the second-level children will be 1.1.1, 1.1.2, etc., and so forth. The actual number of children of each node will be determined by a command-line argument to the program.
     
    The key to building a JTree dynamically is to observe that getChildCount (a method in DefaultMutableTreeNode) will be called before any of the children will actually be retrieved. So you keep a flag indicating whether children have ever been built. So you wait until getChildCount is called, then, if the flag is false, build the children and add them. To keep the tree from trying to count the children (and thus build the nodes) in order to determine which nodes are leaf nodes, override isLeaf to always return false.
     
    4.1 Dynamic Tree: Example Code (Download source code)
     
    import java.awt.*;
    import javax.swing.*;

    public class DynamicTree extends JFrame {
      public static void main(String[] args) {
        int n = 5; // Number of children to give each node
        if (args.length > 0)
          try {
            n = Integer.parseInt(args[0]);
          } catch(NumberFormatException nfe) {
            System.out.println("Can't parse number; using default of " + n);
          }
        new DynamicTree(n);
      }

      public DynamicTree(int n) {
        super("Creating a Dynamic JTree");
        WindowUtilities.setNativeLookAndFeel();
        addWindowListener(new ExitListener());
        Container content = getContentPane();
        JTree tree = new JTree(new OutlineNode(1, n));
        content.add(new JScrollPane(tree), BorderLayout.CENTER);
        setSize(300, 475);
        setVisible(true);
      }
    }
     
    Note: also requires WindowUtilities.java and ExitListener.java, shown earlier.
     
    4.2 OutlineNode.java (Download source code)
     
    import java.awt.*;
    import javax.swing.*;
    import javax.swing.tree.*;

    public class OutlineNode extends DefaultMutableTreeNode {
      private boolean areChildrenDefined = false;
      private int outlineNum;
      private int numChildren;

      public OutlineNode(int outlineNum, int numChildren) {
        this.outlineNum = outlineNum;
        this.numChildren = numChildren;
      }
     
     
    public boolean isLeaf() {
        return(false);
      }

     
    public int getChildCount() {
        if (!areChildrenDefined)
          defineChildNodes();
        return(super.getChildCount());
      }

      private void defineChildNodes() {
        // You must set the flag before defining children if you
        // use "add" for the new children. Otherwise you get an infinite
        // recursive loop, since add results in a call to getChildCount.
        // However, you could use "insert" in such a case.

       
    areChildrenDefined = true;
        for(int i=0; i<numChildren; i++)
          add(new OutlineNode(i+1, numChildren));
      }

      public String toString() {
        TreeNode parent = getParent();
        if (parent == null)
          return(String.valueOf(outlineNum));
        else
          return(parent.toString() + "." + outlineNum);
      }
    }
     
    4.3. Dynamic Tree: Initial Result
     
     
     
    4.4. Dynamic Tree: Result After Expanding A Few Nodes
     
     
     
     
    5. Replacing the Icons at the Tree Nodes
     
    Defining a custom method of drawing a node in a JTree is little different than it was for a JList. See the tutorial section on JList for an example of this general approach. However, one very common task is to simply to change the three icons shown to indicate unexpanded internal (ie non-leaf) nodes, expanded internal nodes, and leaf nodes. This is quite simple -- just make a DefaultTreeCellRenderer, call setOpenIcon, setClosedIcon, and setLeafIcon either with the Icon of interest (usually an ImageIcon made from a small image file) or null to just turn off node icons. Then associate this cell renderer with the tree via setCellRenderer.
     
    5.1 Replacing the Icons: Example Code (Download source code)
     
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    import javax.swing.tree.*;

    /** JTree with missing or custom icons at the tree nodes.
    *  1999 Marty Hall, http://www.apl.jhu.edu/~hall/java/
    */


    public class CustomIcons extends JFrame {
      public static void main(String[] args) {
        new CustomIcons();
      }

     
    private Icon customOpenIcon = new ImageIcon("images/Circle_1.gif");
      private Icon customClosedIcon = new ImageIcon("images/Circle_2.gif");
      private Icon customLeafIcon = new ImageIcon("images/Circle_3.gif");
     
      public CustomIcons() {
        super("JTree Selections");
        WindowUtilities.setNativeLookAndFeel();
        addWindowListener(new ExitListener());
        Container content = getContentPane();
        content.setLayout(new FlowLayout());
        DefaultMutableTreeNode root =
          new DefaultMutableTreeNode("Root");
        DefaultMutableTreeNode child;
        DefaultMutableTreeNode grandChild;
        for(int childIndex=1; childIndex<4; childIndex++) {
          child = new DefaultMutableTreeNode("Child " + childIndex);
          root.add(child);
          for(int grandChildIndex=1; grandChildIndex<4; grandChildIndex++) {
            grandChild =
              new DefaultMutableTreeNode("Grandchild " + childIndex +
                                         "." + grandChildIndex);
            child.add(grandChild);
          }
        }

        JTree tree1 = new JTree(root);
        tree1.expandRow(1); // Expand children to illustrate leaf icons
        JScrollPane pane1 = new JScrollPane(tree1);
        pane1.setBorder(BorderFactory.createTitledBorder("Standard Icons"));
        content.add(pane1);

        JTree tree2 = new JTree(root);
        tree2.expandRow(2); // Expand children to illustrate leaf icons
       
    DefaultTreeCellRenderer renderer2 = new DefaultTreeCellRenderer();
        renderer2.setOpenIcon(null);
        renderer2.setClosedIcon(null);
        renderer2.setLeafIcon(null);
        tree2.setCellRenderer(renderer2);
        JScrollPane pane2 = new JScrollPane(tree2);
        pane2.setBorder(BorderFactory.createTitledBorder("No Icons"));
        content.add(pane2);

        JTree tree3 = new JTree(root);
        tree3.expandRow(3); // Expand children to illustrate leaf icons
       
    DefaultTreeCellRenderer renderer3 = new DefaultTreeCellRenderer();
        renderer3.setOpenIcon(customOpenIcon);
        renderer3.setClosedIcon(customClosedIcon);
        renderer3.setLeafIcon(customLeafIcon);
        tree3.setCellRenderer(renderer3);
        JScrollPane pane3 = new JScrollPane(tree3);
        pane3.setBorder(BorderFactory.createTitledBorder("Custom Icons"));
        content.add(pane3);

        pack();
        setVisible(true);
      }
    }
     
    Note: also requires WindowUtilities.java and ExitListener.java, shown earlier.
     
    5.2. Replacing the Icons: Result
     
     
     
    반응형

    아래의 코드를 가지고 실행가능한 JAR 파일을 만든다고 가정합니다.

    public class HelloApp {

     private String name = "";
     public HelloApp(String name) {
     this.name = name;
    }

    public void sayHello() {
     System.out.println("Hello, my name is " + name + ".");
     }

     public static void main(String[] args) {
      HelloApp app;
      if (args.length > 0)
       app = new HelloApp(args[0]);
      else
       app = new HelloApp("RESISA~");
      app.sayHello();
     }
    }

    아래의 순서에 따라 만들면 됩니다.. ^_^;

    1. Compile:

    Prompt> javac HelloApp.java

    2. Make a menifest file "MANIFEST.MF".

    Prompt> mkdir META-INF
    Prompt> edit META-INF\MANIFEST.MF

    [Remark]
    MENIFEST.MF must contain at least the following line.
    Main-Class: HelloApp

    3. Create a jar file "hello.jar" by using such a command
    jar cmf {manifest file} {jar file} {class files}

    Prompt> jar cmf "META-INF\MANIFEST.MF" hello.jar HelloApp.class

    4. Execute:

    Prompt> java -jar hello.jar
    Prompt> java -jar hello.jar "Duke Java!"

    반응형
    [1] Java Q & A
        Free Java E-Books & Tutorials
        http://www.perryland.com/Java9.shtml
    
    [2] e-Book
        Bruce Eckel's Free Electronic Books
        http://www.smart2help.com/e-books/
    
    
    유명한 Thinking 시리즈입니다.
    (3rd Edition은 아직 베타입니다.)
    
    [1] Thinking in Java 홈페이지
        http://www.mindview.net/Books/TIJ/
    
    [2] 책을 PDF 문서로 직접 받아 볼 수 있는 곳
        http://www.codecuts.com/mainpage.asp?WebPageID=314&MenuID=141
    
    [3] 2nd, 3rd editions의 모든 소스 코드가 있는 곳
        (Java 이외에 C++ 자료도 있습니다.) 
        Bruce Eckel's Free Electronic Books
        http://www.smart2help.com/e-books/
    
    [4] 공짜로 보는 Java 전자 책의 다운로드 링크가 잔뜩 있는 곳
        http://www.mindview.net/Books/DownloadSites/
    
    [*] 자바클루가 제공하는 Java 전자 책 목록
        http://www.javaclue.org/ebooks/index.jsp
    
        
    from:
    www.javaclue.org
    반응형

    요약

    이번 튜토리얼에서는 Jigloo를 사용하여 기본적인 GUI를 생성하는 방법을 살펴보았다. 몇 가지 컨테이너와 컨트롤들을 사용해 봤다. 이벤트를 사용하여 각각의 컨트롤을 비즈니스 로직을 구현해 놓은 모델과 엮는 방법도 살펴보았다. 이제부터 할 수 있는 것이 많아졌을 것이다. Jigloo의 좀 더 어려운 기능들도 사용할 준비가 되었다. Jigloo를 사용하여 다음과 같은 일들을 할 수 있다.

    • 폼에서 재사용 가능하고 분리된 컴포넌트들을 추출
    • 이런 컴포넌트들을 다른 애플리케이션에서 사용할 수 있으며 심지어 비주얼 상속을 사용하여 확장(extend)할 수도 있다.
    • 스윙 컴포넌트 추가
    • 전체 애플리케이션을 스윙으로 변환

    Jigloo 구조상 좀 더 다양한 특징을 제공하기 때문에 폼을 좀 더 복잡하게 만들 수 있다. 날짜 선택 컨트롤과 이런 데이터 요소를 위한 콤보 컨트롤을 사용할 수 있다.

    애플리케이션에서 Jigloo 사용에 대해서는 참고자료에 있는 추가 문서들과 개념을 참조하기 바란다.

    기사의 원문보기

    <출처 :https://www.ibm.com/developerworks/kr/library/tutorial/os-eclipse-jigloo/section5.html>

    다운로드 하십시오

    설명 이름 크기 다운로드 방식
    Part 4 source code os-eclipse-jigloo.workflow.zip 18KB HTTP
    다운로드 방식에 대한 정보

    <출처 :https://www.ibm.com/developerworks/kr/library/tutorial/os-eclipse-jigloo/section6.html>

    참고자료

    교육

    제품 및 기술 얻기

    토론
    • 이클립스 플랫폼 뉴스그룹에서 이클립스 관련 궁금증을 해결할 수 있을 것이다(링크를 클릭하면 기본 유즈넷 뉴스 리더 애플리케이션을 실행하고 eclipse.platform을 자동으로 열 것이다).

    • The 이클립스 뉴스그룹에는 이클립스를 확장하고 사용하는 것에 관심 있는 사람들을 위한 많은 참고자료가 있다.

    • 이클립스 플랫폼 SWT 메일링 리스트를 구독하여 최신 이클립스 소식을 얻을 수 있다.

    • developerWorks 블로그와 developerWorks 커뮤니티에 참여할 수 있다.

      <출처 :https://www.ibm.com/developerworks/kr/library/tutorial/os-eclipse-jigloo/section7.html>
    반응형

    애플리케이션에서 사용할 데이터 모델 만들기

    모델-뷰-컨트롤(MVC) 아키텍처에 익숙하다면 지금까지 만든 것이 애플리케이션의 뷰에 해당한다는 것을 알아차렸을 것이다. 이 부분이야 말로 Jigloo가 진가를 발휘하는 부분이다. 이제는 모델을 만들어야 한다. 다시 말하면 시스템에서 사용할 데이터를 가져오고 사용할 자바 코드를 만들어야 함을 의미한다. Jigloo는 여기서도 역시 빛을 발한다. Jigloo는 단순한 이클립스 플러그인으로 Jigloo를 사용할 때도 직접 이클립스의 강력한 기능들을 힘들이지 않고 바로 사용할 수 있다. 이클립스는 자바 코드 작성과 데이터를 다루는 데 매우 훌륭한 도구이기 때문에 Jigloo 역시 이런 작업을 하기에 적합하다.

    스키마 만들기

    언급했다시피, XML 형식으로 데이터를 저장하고 JAXB를 사용하여 XML을 읽고 쓰는 작업을 할 것이다. 따라서 스키마를 작성할 필요가 있다.


    Listing 1. 워크플로우 XML 스키마
                        
    <?xml version="1.0" encoding="UTF-8"?>
    <schema xmlns="http://www.w3.org/2001/XMLSchema" 
      targetNamespace="org:developerworks:workflow" 
      xmlns:dw="org:developerworks:workflow">
    
         <element name="workflow" type="dw:workflow"/>
         <complexType name="workflow">
              <sequence>
                   <element name="user" type="dw:user" minOccurs="0"
    maxOccurs="unbounded"/>
                   <element name="po" type="dw:purchaseOrder"
    minOccurs="0" maxOccurs="unbounded"/>
              </sequence>
         </complexType>
         
         <complexType name="user">
              <sequence>
                   <element name="username" type="string"/>
                   <element name="role" type="dw:role"/>
              </sequence>
              <attribute name="id" type="integer" use="required"/>
         </complexType>
         <simpleType name="role">
              <restriction base="string">
                   <enumeration value="worker"/>
                   <enumeration value="manager"/>
              </restriction>
         </simpleType>
         
         <complexType name="purchaseOrder">
              <sequence>
                   <element name="priority" type="dw:priority"/>
                   <element name="dateRequested" type="date"/>
                   <element name="dateNeeded" type="date" minOccurs="0"/>
                   <element name="itemName" type="string"/>
                   <element name="itemDescription" type="string" minOccurs="0"/>
                   <element name="quantityRequested" type="integer"/>
                   <element name="url" type="anyURI" minOccurs="0"/>
                   <element name="price" type="decimal"/>
                   <element name="status" type="dw:orderStatus"/>
                   <element name="submittedBy" type="integer"/>
                   <element name="processedBy" type="integer" minOccurs="0"/>
              </sequence>
              <attribute name="id" type="integer" use="required"/>
         </complexType>
         
         <simpleType name="priority">
              <restriction base="string">
                   <enumeration value="normal"/>
                   <enumeration value="high"/>
              </restriction>
         </simpleType>
         
         <simpleType name="orderStatus">
              <restriction base="string">
                   <enumeration value="pending"/>
                   <enumeration value="approved"/>
                   <enumeration value="rejected"/>
              </restriction>
         </simpleType>
    </schema>
    

    스키마에 해당하는 XML 파일에 바인딩할 자바 클래스를 만들기 위해 JAXB를 사용할 수 있다. 자바 6을 사용한다면 JAXB가 내장되어 있다. 자바 5를 사용한다면 썬에서 JAXB를 다운로드해야 한다. 여러분은 명령행 도구인 xjc를 사용하길 원할 수도 있다. 예를 들어 xjc workflow.xsd와 같이 사용할 수 있다. 이 명령어를 사용하여 workflow.xsd를 스키마 컴파일러가 파싱하고 클래스를 만들어낼 것이다. 그런 다음 클래스 파일들을 프로젝트에 복사하여 사용할 수 있다. 프로젝트에 XML 디렉터리를 만들고 그 안에 스키마 파일도 복사한다. 이제 예제로 사용할 XML 파일을 만들자.


    Listing 2. 초기 XML 데이터
                        
    <?xml version="1.0" encoding="UTF-8"?>
    <dw:workflow xmlns:dw="org:developerworks:workflow"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="org:developerworks:workflow
    workflow.xsd ">
      <user id="0">
        <username>homer</username>
        <role>worker</role>
      </user>
      <user id="1">
        <username>bart</username>
        <role>manager</role>
      </user>
      <po id="0">
        <priority>normal</priority>
        <dateRequested>2001-01-01</dateRequested>
        <dateNeeded>2001-01-01</dateNeeded>
        <itemName>stapler</itemName>
        <itemDescription>A great stapler</itemDescription>
        <quantityRequested>2</quantityRequested>
        <url>http://www.thinkgeek.com/homeoffice/gear/61b7/</url>
        <price>21.99</price>
        <status>pending</status>
        <submittedBy>0</submittedBy>
      </po>
    </dw:workflow>
    

    모든 요소들을 추가한 뒤 Package Explorer는 그림 26처럼 보일 것이다(필요하다면 JAXB jar 파일들을 자바 빌드 패스에 추가해야 한다).


    그림 26. JAXB 클래스와 XML 파일이 추가된 Package explorer
    JAXB 클래스와 XML 파일이 추가된 Package explorer




    위로


    데이터 접근

    Package Explorer에 몇 가지 파일들이 추가된 것을 확인할 수 있을 것이다. 바로 WorkflowDao와 XmlWorkflow다. WorkflowDao는 데이터를 사용할 때 필요로 하는 작업들을 정의한 인터페이스다(Listing 3).


    Listing 3. WorkflowDao 인터페이스
                        
    package org.developerworks.workflow;
    
    import java.util.List;
    
    public interface WorkflowDao {
         public List<User> getUsers();
         public List<PurchaseOrder> getAllOrders();
         public List<PurchaseOrder> getAllPendingOrders();
         public List<PurchaseOrder> getOrdersForUser(int userId);
         public void saveOrder(PurchaseOrder order);
         public void setOrderStatus(int orderId, OrderStatus status);
    }
    

    고전적인 데이터 접근 객체(Data Access Object) 패턴을 사용하고 있다. 간단하게 인터페이스를 정의하고 이 인터페이스에 대한 애플리케이션 코드를 작성한다. XML을 사용하여 JAXB 기반 구현을 할 것이다. 하지만 이 디자인을 사용하여 손쉽게 데이터베이스 기반 구현 같은 기타 구현으로 변경할 수 있다. 이 인터페이스의 구현체가 XmlWorkFlow다.


    Listing 4. XmlWorkflow 인터페이스 구현
                        
    package org.developerworks.workflow;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.InputStream;
    import java.math.BigInteger;
    import java.util.ArrayList;
    import java.util.List;
    
    import javax.xml.bind.JAXBContext;
    import javax.xml.bind.JAXBElement;
    import javax.xml.bind.JAXBException;
    import javax.xml.bind.Marshaller;
    import javax.xml.bind.Unmarshaller;
    
    public class XmlWorkflow implements WorkflowDao {
         private static final String DATA_FILE = "data.xml";
         private static XmlWorkflow instance;
         
         private Workflow workflow;
         
         private XmlWorkflow() {
              try {
                   JAXBContext ctx = this.getContext();
                   Unmarshaller unm = ctx.createUnmarshaller();
                   File dataFile = this.getDataFile();
                   InputStream inputStream;
                   if (dataFile.exists() && dataFile.length() > 0){
                        inputStream = new FileInputStream(dataFile);
                   } else {
                        inputStream = 
    Thread.currentThread().getContextClassLoader().getResourceAsStream("xml/"+DATA_FILE);
                   }
                   JAXBElement element = (JAXBElement) unm.unmarshal(inputStream);
                   this.workflow = (Workflow) element.getValue();
              } catch (JAXBException e) {
                   e.printStackTrace();
                   throw new RuntimeException("Failed to read data file",e);
              } catch (FileNotFoundException e) {
                   e.printStackTrace();
                   throw new RuntimeException("Could not open data file", e);
              }
         }
         
         public static XmlWorkflow getInstance(){
              if (instance == null){
                   instance = new XmlWorkflow();
              }
              return instance;
         }
    
         public List<PurchaseOrder> getAllOrders() {
              return this.workflow.getPo();
         }
    
         public List<PurchaseOrder> getAllPendingOrders() {
              List<PurchaseOrder> allOrders = this.getAllOrders();
              List<PurchaseOrder> pending = new ArrayList<PurchaseOrder>();
              for (PurchaseOrder order : allOrders){
                   if (order.getStatus().equals(OrderStatus.PENDING)){
                        pending.add(order);
                   }
              }
              return pending;
         }
    
         public List<PurchaseOrder> getOrdersForUser(int userId) {
              List<PurchaseOrder> allOrders = this.getAllOrders();
              List<PurchaseOrder> userOrders = new ArrayList<PurchaseOrder>();
              for (PurchaseOrder order : allOrders){
                   if (order.getSubmittedBy().intValue() == userId){
                        userOrders.add(order);
                   }
              }
              return userOrders;
         }
    
         public List<User> getUsers() {
              return this.workflow.getUser();
         }
    
         public void saveOrder(PurchaseOrder order) {
              int index = 0;
              for (PurchaseOrder po : this.workflow.getPo()){
                   if (po.getId().intValue() == order.getId().intValue()){
                        this.workflow.getPo().set(index, order);
                        this.saveData();
                        return;
                   }
                   index++;
              }
              // add new order
              order.setId(new BigInteger(Integer.toString(this.workflow.getPo().size())));
              this.workflow.getPo().add(order);
              this.saveData();
         }
         
         public void setOrderStatus(int orderId, OrderStatus status) {
              for (PurchaseOrder po : this.workflow.getPo()){
                   if (po.getId().intValue() == orderId){
                        po.setStatus(status);
                        this.saveData();
                        return;
                   }
              }
         }
    
         private void saveData(){
              File dataFile = this.getDataFile();
              try {
                   JAXBContext ctx = this.getContext();
                   Marshaller marshaller = ctx.createMarshaller();
                   FileOutputStream stream = new FileOutputStream(dataFile);
                   marshaller.marshal(this.workflow, stream);
              } catch (JAXBException e) {
                   e.printStackTrace();
                   throw new RuntimeException("Exception serializing data file",e);
              } catch (FileNotFoundException e) {
                   e.printStackTrace();
                   throw new RuntimeException("Exception opening data file");
              }
         }
         
         private File getDataFile() {
              String tempDir = System.getProperty("java.io.tmpdir");
              File dataFile = new File(tempDir + File.separatorChar + DATA_FILE);
              return dataFile;
         }
    
         private JAXBContext getContext() throws JAXBException {
              JAXBContext ctx = JAXBContext.newInstance("org.developerworks.workflow");
              return ctx;
         }
         
         public static void main(String[] args){
              XmlWorkflow dao = XmlWorkflow.getInstance();
              List<User> users = dao.getUsers();
              assert(users.size() == 2);
              for (User user : users){
                   System.out.println("User: " + user.getUsername() + " ID:" + user.getId());
              }
              List<PurchaseOrder> orders = dao.getAllOrders();
              assert(orders.size() == 1);
              for (PurchaseOrder order : orders){
                   System.out.println("Order:" + order.getItemName() + "
    ID:" + order.getId() + " Status:" + order.getStatus());
              }
              PurchaseOrder order = orders.get(0);
              order.setStatus(OrderStatus.APPROVED);
              order.setProcessedBy(new BigInteger("1"));
              dao.saveOrder(order);
         }
    }
    

    위에서 만들었던 예제 파일을 초기에 읽어 들이는 것을 확인할 수 있지만 시스템 임시 폴더에 data.xml로 변경사항을 저장한다. 데이터를 저장하기에 가장 안전한 장소는 아니지만 예제 애플리케이션에 사용하기에는 적절하다. 이 클래스 파일 안에 간단한 main 메서드가 있는 것 또한 볼 수 있다. JAXB가 동작하는 것을 간단하게 단위 테스트하기 위한 용도로 만들었다. 만약에 자바 5를 사용한다면 JAXB jar 파일을 프로젝트의 클래스패스에 추가해야 한다. 계속해서 작업하려면 그 파일들을 복사하여 프로젝트에 추가하거나 프로젝트 외부에 그 파일들이 위치한 장소를 참조할 수 있도록 해야 한다.




    위로


    애플리케이션 초기화하기

    애플리케이션과 인터랙트하기 전에 모든 요소를 초기화해야 한다. 먼저 애플리케이션에서 사용할 모델 객체를 몇 개 선언해야 한다. Listing 5에 있는 코드를 추가하여 WorkflowMain 멤버 변수를 추가한다.


    Listing 5. 모델 객체 선언
                        
         // Data Model Objects
         private java.util.List<User> users;
         private User user;
         
         // Service Object
         private WorkflowDao dao = XmlWorkflow.getInstance();
    

    코드에 접근하려면 Workflow.java 파일을 마우스 오른쪽 클릭을 하고 Open With > Java Editor를 선택한다.

    애플리케이션의 initGUI() 메서드 코드를 수정한다. 사용자 명단을 초기화하기 위해 private 메서드를 만들겠다.


    Listing 6. 사용자 메서드 만들기
                        
         private void initUserList(){
              this.users = dao.getUsers();
              for (User u : users){
                   this.userListCombo.add(u.getUsername());
              }
         }
    

    userListCombo를 정의한 후 initGUI()에서 이 메서드를 호출한다.


    Listing 7. 사용자 메서드 호출
                        
                    {
                        userListCombo = new Combo(this, SWT.NONE);
                        userListCombo.setText("Users");
                        userListCombo.setBounds(28, 35, 105, 21);
                        this.initUserList();
                   }
    




    위로


    이벤트를 사용하여 뷰와 모델을 엮기

    뷰와 모델을 만들었다. 이제 그 둘을 엮어 보자. 컨트롤러가 필요하다. SWT(와 스윙)는 모든 UI 프레임워크에서 사용하는 간단한 기술을 사용한다. 바로 이벤트 주도 시스템이라는 것이다. 이벤트를 사용하여 언제 모델에 있는 작업을 호출하고 뷰를 수정할지 알려줄 수 있다.

    이제 다시 비주얼 디자이너로 돌아가자. 모델과 엮기를 원하는 첫 번째 UI 이벤트는 사용자 콤보 리스트에서 사용자를 선택했을 때다. 콤보 컨트롤을 선택하고 GUI 속성 뷰에서 Event 탭으로 변경하면 그림 27에 보이는 것과 같은 화면을 확인할 수 있을 것이다.


    그림 27. 콤보 컨트롤 이벤트에 접근하기
    콤보 컨트롤 이벤트에 접근하기

    몇몇 리스너들을 콤보 컨트롤에서 볼 수 있다. SelectionListener를 선택한다. 이 리스너는 콤보 컨트롤에서 무언가를 선택할 때마다 SelectionEvent를 발생시킨다. 이 이벤트를 다룰 것을 익명 메서드로 그것을 인라인에서 다룰 수도 있고이 이벤트를 다룰 메서드를 정의할 수도 있다. 후자를 선택하겠다. 이렇게 하면 userListComboWidgetSelected라는 메서드가 생성된다. 이벤트를 다루기 위한 코드는 Listing 8에 나와있다.


    Listing 8. 사용자 콤보 리스트 선택 코드
                        
         private void userListComboWidgetSelected(SelectionEvent evt) {
              int index = this.userListCombo.getSelectionIndex();
              if (index >= 0){
                   this.user = this.users.get(index);
                   System.out.println("User selected="+this.user.getUsername());
                   purchaseOrderTable.removeAll();
                   java.util.List<PurchaseOrder> orders;
                   boolean isManager = this.user.getRole().equals(Role.MANAGER);
                   if (isManager){
                        orders = dao.getAllPendingOrders();
                   } else {
                        orders = dao.getOrdersForUser(this.user.getId().intValue());
                   }
                   this.approveButton.setVisible(isManager);
                   this.rejectButton.setVisible(isManager);
                   for (PurchaseOrder order : orders){
                        displayPurchaseOrder(order);
                   }
              }
         }
    

    여기서 살펴봐야 할 것들이 많다. 먼저 사용자가 관리자인지 확인한다. 관리자가 아니면 사용자의 모든 구매 주문 목록을 보여준다. 관리자가 맞다면 대기중인 주문 목록만을 보여준다. 다음으로 관리자가 아니면 승인/취소 버튼이 보이지 않도록 한다. 마지막으로 purchaseOrderTable에 있는 모든 주문 데이터들을 데이터 접근 객체를 사용해 가져와 보여준다.

    이제 Approve 버튼에 이벤트를 추가한다. 비주얼 디자이너에 보이는 Approve 버튼을 선택하고 GUI 속성 창에 있는 이벤트 탭으로 이동한다. 버튼을 선택했을 때 실행되어야 하기 때문에 그림 28에 보이는 것처럼 여기서도 selection event를 사용할 것이다.


    그림 28. Approve 버튼 선택 이벤트 설정
    Approve 버튼 선택 이벤트 설정

    그리고 나서 이 이벤트를 다룰 코드를 추가한다.


    Listing 9. Approve 버튼 선택 이벤트 코드
                        
         private void approveButtonWidgetSelected(SelectionEvent evt) {
              TableItem[] selected = this.purchaseOrderTable.getSelection();
              if (selected != null){
                   for (TableItem item : selected){
    	this.dao.setOrderStatus(Integer.parseInt(item.getText(4)), OrderStatus.APPROVED);
                        item.setText(3, OrderStatus.APPROVED.toString());
                   }
              }
         }
    

    reject 버튼도 이와 매우 비슷하게 할 수 있다. 선택 이벤트 리스너를 추가하고 비슷한 코드를 실행한다. 유일한 차이가 있다면 주문 상태를 APPROVED가 아닌 REJECTED로 바꾼다는 것이다.


    Listing 10. Reject 버튼 코드
                        
         private void rejectButtonWidgetSelected(SelectionEvent evt) {
              TableItem[] selected = this.purchaseOrderTable.getSelection();
              if (selected != null){
                   for (TableItem item : selected){
    	this.dao.setOrderStatus(Integer.parseInt(item.getText(4)), OrderStatus.REJECTED);
                        item.setText(3, OrderStatus.REJECTED.toString());
                   }
              }
         }
    

    이제 남은 건 Submit 버튼이다. 이 버튼을 사용하여 새로운 구매 주문을 추가할 수 있어야 한다. 이 버튼 역시 다른 버튼들과 유사하다. 선택 이벤트에 대한 이벤트 핸들러를 그림 29처럼 추가한다.


    그림 29. PO 버튼 선택 리스너 추가
    PO 버튼 선택 리스너 추가

    이벤트를 다룰 코드를 추가한다.


    Listing 11. PO 버튼 이벤트 핸들러 코드 추가
                        
    import java.math.BigDecimal;
    import java.math.BigInteger;
    import java.util.GregorianCalendar;
    
    import javax.xml.datatype.DatatypeFactory;
    import javax.xml.datatype.XMLGregorianCalendar;
    
    ...
    
         private void addButtonWidgetSelected(SelectionEvent evt) {
              try {
                   this.addPurchaseOrder();
              } catch (Exception e) {
                   throw new RuntimeException("Exception adding purchase order",e);
              }
              this.formItemText.clearSelection();
              this.formPriceText.clearSelection();
              this.formQuantityText.clearSelection();
         }
         
         private void addPurchaseOrder() throws Exception{
              String item = this.formItemText.getText();
              String priceString = this.formPriceText.getText();
              String quantityString = this.formQuantityText.getText();
              BigDecimal price = new BigDecimal(priceString);
              BigInteger quantity = new BigInteger(quantityString);
              PurchaseOrder po = new PurchaseOrder();
              int num = this.dao.getAllOrders().size();
              String numString = Integer.toString(num);
              BigInteger newId = new BigInteger(numString);
              po.setId(newId);
              po.setItemName(item);
              po.setPrice(price);
              po.setQuantityRequested(quantity);
              po.setPriority(Priority.NORMAL);
              po.setStatus(OrderStatus.PENDING);
              po.setSubmittedBy(this.user.getId());
              GregorianCalendar cal = (GregorianCalendar) GregorianCalendar.getInstance();
              DatatypeFactory factory = DatatypeFactory.newInstance();
              XMLGregorianCalendar now = factory.newXMLGregorianCalendar(cal);
              po.setDateRequested(now);
              this.dao.saveOrder(po);
              this.displayPurchaseOrder(po);
         }
    
    	private void displayPurchaseOrder(PurchaseOrder order) {
    		String[] row = new String[] 
    		         {order.getItemName(), order.getPrice().toString(), 
    				order.getQuantityRequested().toString(),
    order.getStatus().toString(), order.getId().toString()};
    		TableItem tableItem = new TableItem(purchaseOrderTable,0);
    		  tableItem.setText(row);
    		  this.purchaseOrderTable.showItem(tableItem);
    	}
    




    위로


    GUI 테스트

    GUI를 테스트해야 할 시간이다. 그림 30처럼 클래스를 오른쪽 클릭을 한 후 Run As > SWT Application을 선택한다.


    그림 30. 애플리케이션 실행
    애플리케이션 실행

    이렇게 하면 애플리케이션이 실행된다.


    그림 31. 워크플로우 애플리케이션
    워크플로우 애플리케이션

    기본 데이터로 대기중인 구매 주문을 넣어뒀기 때문에 사용자 bart를 선택한 뒤 구매 주문을 승인할 수 있다.


    그림 32. 주문 승인
    주문 승인

    사용자를 homer로 변경한 뒤 구매 주문의 상태를 확인해 보자.


    그림 33. 사용자가 자기 PO 보기
    사용자가 자기 PO 보기

    새로운 주문을 추가할 수도 있다.


    그림 34. PO 추가
    PO 추가

    Add PO를 클릭하여 테이블에 구매 주문을 추가할 수 있다.


    그림 35. 새 PO 추가
    새 PO 추가

    다시 bart로 변경하여 승인 또는 취소할 수 있다.


    그림 36. 업데이트된 관리자 화면
    업데이트된 관리자 화면 

    + Recent posts