WindowBuilder Pro

java UI 2011. 9. 1. 18:30

오랜만에 swing code를 하려고 했더니. 좀 귀찮았다.  스택 오버플로우에서 자바 UI Builder 중에 구글의 windowBuilder Pro 버전을 공개중이다.
(음.. 7년 전만 해도 이런 툴은 돈주고 사야했었다...^^;;)

http://code.google.com/intl/ko-KR/javadevtools/wbpro/index.html


설치방법은 이클립스 플러그인 설치와 동일하다. 아래 주소로 설치한다. 


Eclipse 3.7 (Indigo)

http://dl.google.com/eclipse/inst/d2wbpro/latest/3.7


Eclipse 3.6 (Helios)

http://dl.google.com/eclipse/inst/d2wbpro/latest/3.6


Eclipse 3.5 (Galileo)

http://dl.google.com/eclipse/inst/d2wbpro/latest/3.5


Eclipse 3.4 (Ganymede)

http://dl.google.com/eclipse/inst/d2wbpro/latest/3.4



설치 하고 나면  new project 하면 window builder 라는 디렉토를 확인할 수 있다.
RCP 라던가 GWT, Swing,  프로젝트를 생성할 수 있다.


스윙 쪽은 여기를 참조하면서 하면 된다.
http://code.google.com/intl/ko-KR/javadevtools/wbpro/features/swing/data_binding/example.html






실제로 막상 쓸라면 좀 어려운 데..
아래 그림처럼  Swing component를 추가할 수 있는 툴바를 잘 찾아서 사용하면 편하게 사용가능하다..





나머지는 구글에서의 스크린샷.












'java UI' 카테고리의 다른 글

WindowBuilder Pro  (0) 2011.09.01
jsp 2.0 사용시 예제  (0) 2009.01.01
quartz 를 이용하기  (0) 2008.01.22
File Connection Optiobal Package  (0) 2006.02.28
[펌] DataSource의 복제를 통한 다중 플레이어 생성방법  (0) 2005.12.02
jtable tutorial  (0) 2005.02.16
Posted by 김용환 '김용환'

댓글을 달아 주세요

jsp 2.0 사용시 예제

java UI 2009. 1. 1. 04:18

http://pdf.coreservlets.com/JSP-EL.pdf

 

 

 

 <script language="javascript">

 function preview(form) {
  window.open("", "previewPopup", "width=800, height=600");
  form.m.value = "preview";
  form.target = "previewPopup";
  form.submit();
 }
 </script>   

 

 


 <c:forEach items="${list}" var="page" varStatus="status">
 <form method="post" action="/under/emergencyui.nhn" name="ui${status.index}">
    <tr>   
      <td>
       ID : <input name="id" value="${page.id}" size=1 disabled=true/>의  내용
      </td>
      <td>
       <textarea name="content" rows=15 cols=90><c:out value="${page.content}" escapeXml="true" /></textarea><br>
      </td>
      <td>
        <c:out value="${status.index}" />
   <input type="hidden" name="m" value="preview"/>
   <input type="button" value="미리보기" onclick="preview(ui${status.index})">
      <input type="button" value="저장" onclick="save()">
    </td>
    </tr>
    </form>
 </c:forEach>

 

 

'java UI' 카테고리의 다른 글

WindowBuilder Pro  (0) 2011.09.01
jsp 2.0 사용시 예제  (0) 2009.01.01
quartz 를 이용하기  (0) 2008.01.22
File Connection Optiobal Package  (0) 2006.02.28
[펌] DataSource의 복제를 통한 다중 플레이어 생성방법  (0) 2005.12.02
jtable tutorial  (0) 2005.02.16
Posted by 김용환 '김용환'

댓글을 달아 주세요

quartz 를 이용하기

java UI 2008. 1. 22. 23:56

 <?xml version='1.0' encoding='MS949'?>
<!DOCTYPE quartz PUBLIC
  "-//Quartz Enterprise Job Scheduler//DTD Job Scheduling Data 1.5//EN"
  "http://www.quartzscheduler.org/dtd/job_scheduling_data_1_5.dtd">

<quartz>
  <job>

    <job-detail>
      <name>RankingCron</name>
      <group>RankingCrons</group>
      <job-class>com.google.beginning.bo.RankingCronBO</job-class>
      <volatility>false</volatility>
      <durability>false</durability>
      <recover>false</recover>
    </job-detail>

 

    <trigger>
 

      <cron>
        <name>60</name>
        <group>cacheTriggers</group>
        <job-name>RankingCron</job-name>
        <job-group>RankingCrons</job-group>
        <cron-expression>1 * * * * ?</cron-expression>
      </cron>

    </trigger>
  </job>

</quartz>

 

 

실제 자바 소스는 다음과 같다.

 
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;


public class RankingCronBO  implements Job {
    private static Log log = LogFactory.getLog(RankingCronBO.class);

    public void execute(JobExecutionContext context)
            throws JobExecutionException {
        log.info("RankingCronBO");

    }
}

 

'java UI' 카테고리의 다른 글

WindowBuilder Pro  (0) 2011.09.01
jsp 2.0 사용시 예제  (0) 2009.01.01
quartz 를 이용하기  (0) 2008.01.22
File Connection Optiobal Package  (0) 2006.02.28
[펌] DataSource의 복제를 통한 다중 플레이어 생성방법  (0) 2005.12.02
jtable tutorial  (0) 2005.02.16
Posted by 김용환 '김용환'

댓글을 달아 주세요

Article
An Overview of the File Connection Optional Package
 


 

New J2ME developers are often surprised to discover that the Connected Limited Device Configuration (CLDC) and the profiles based on it are not required to support the reading or writing of files. The Generic Connection Framework (GCF) defined by the CLDC does provide the basic scaffolding for file I/O, primarily through the InputConnection, OutputConnection, and StreamConnection interfaces, but it's up to specific implementations to expose this capability to applications. This limitation isn't a bad thing: It allows the CLDC to be ported to devices without a file system. (Such devices are more popular than you might think: devices running Palm OS, for example, do not support file systems in main memory, only on memory expansion cards.) If a file system is supported, however, it would be nice to have a standard way of using it through the GCF. This is the purpose of the File Connection Optional Package.

The File Connection Optional Package (FCOP) is one of two optional packages defined by JSR 75 through the Java Community Process. The other, the PIM Optional Package, is discussed in another tech tip. Because the FCOP specification is still a draft standard and no reference implementation is yet available, the information presented here is still subject to change.

If you're not familiar with optional packages, see the article "J2ME Optional Packages" for details on how they work. Simply put, an optional package is a set of programming interfaces that can be added to a J2ME profile or configuration to provide a category of functionality that some users of that configuration or profile will need but not all. FCOP can be supported on any J2ME platform, because it depends only on the core classes defined by the CLDC, and thus included in the Connected Device Configuration (CDC) as well.

You can write applications that use FCOP in two ways. If all you want to do is read files, you can use the "file:" URL prefix to obtain an InputConnection interface to a file. For example:

... import javax.microedition.io.*; String url = "file:///data.txt"; InputConnection conn = null; int mode = Connector.READ_ONLY; try { conn =(InputConnection) Connector.open( url, mode ); } catch( IOException ioe ){ // no file } ...

This code can be used on any platform that exposes the file system through the GCF, whether it supports FCOP or not. The Connected Device Configuration (CDC) and the profiles based on it all support this method of reading files, for example. Such a platform may also allow writing to files if you specify the Connector.READ_WRITE or Connector.WRITE_ONLY mode, returning a StreamConnection or an OutputConnection as appropriate.

The second way to use FCOP is through the new FileConnection interface. Before doing so, however, an application should ensure that FCOP is available, by checking for the presence of the microedition.io.file.FileConnection.version property:

... // Check that the File Connection Optional Package is there String v = System.getProperty( "microedition.io.file.FileConnection.version" ); if( v != null ){ // FCOP available } else { // FCOP not available } ...

The value of the property is the version number of FCOP, which for the first release is "1.0".

When FCOP is supported, all GCF connections made using the "file:" protocol return an instance of javax.microedition.io.file.FileConnection. FileConnection extends StreamConnection by adding methods for file and directory manipulation. The added functionality is similar to that available in J2SE's java.io.File class. The general format for opening a file is a URL of the form:

file://host/path

This is the format defined in Section 3.10 of RFC 1738, the document that defines the general format of a URL. Devices are unlikely to support file access across a network, so in almost every case the URL will refer to the local host, and the host part of the URL is commonly omitted. What's left, then, is the path part, consisting of a root (identifying the root directory of a mounted file system) and a file or directory path. On a Windows platform, for example, a valid URL might be:

file:///c:/Program Files/Windows NT/Pinball/table.bmp

On a device with memory expansion slots the URL might look like this:

file:///SDCard/users.txt

Because the number and names of mounted file systems vary from device to device, a support class is provided that lets applications list the available file systems. This FileSystemRegistry class (defined in the javax.microedition.io.file package) also notifies interested applications whenever the user inserts or removes a memory expansion card from the device.

The file URL passed to Connector.open() normally refers to an existing file or directory. For example, here's how to obtain the list of files in a directory:

... String url = "file:///SDCard"; FileConnection conn = null; try { conn = (FileConnection) Connector.open( url ); if( conn.isDirectory() ){ Enumeration names = conn.list(); while( names.hasMoreElements() ){ String name = (String) e.nextElement(); // do something } } else { // not a directory! } } catch( IOException e ){ // could not access the URL } catch( SecurityException e ){ // no permission to read the directory } ...

The URL can also refer to files or directories that don't yet exist. You can create a file using FileConnection.create(), for example:

... String url = "file:///SDCard/myfile.txt"; FileConnection conn = null; try { conn = (FileConnection) Connector.open( url, Connector.WRITE_ONLY ); if( conn.create() ){ // create the file OutputStream out = conn.openOutputStream(); // now write data to the file } conn.close(); } catch( IOException e ){ // error } catch( SecurityException e ){ // no permission to create/write } ...

Note that almost every method in the FileConnection class has the potential to throw a SecurityException. The FCOP specification does not define a specific security model for controlling access to the file system, leaving that task to the configuration or profile that incorporates FCOP.

We've only touched on a few aspects of FCOP. For full details, check out the Javadoc for the FCOP classes.



Back To Top

 

출처 : http://developers.sun.com/techtopics/mobility/apis/ttips/fileconnection/

'java UI' 카테고리의 다른 글

jsp 2.0 사용시 예제  (0) 2009.01.01
quartz 를 이용하기  (0) 2008.01.22
File Connection Optiobal Package  (0) 2006.02.28
[펌] DataSource의 복제를 통한 다중 플레이어 생성방법  (0) 2005.12.02
jtable tutorial  (0) 2005.02.16
The Eclipse runtime options  (0) 2005.02.15
Posted by 김용환 '김용환'

댓글을 달아 주세요

DataSource의 복제를 통한 다중 플레이어 생성방법


안녕하세요. 지난번 강좌까지 실험 잘 하셨나요?
지난 번 까지의 소스만으로도 간단한 영상 음성 기록 프로그램을 만들수도 있고, 캡쳐 카드가 있다면, 비디오 카메라의 영상 출력을 캡쳐 카드의 입력단으로 연결하고, 프로그램을 약간 수정한다면, 컴퓨터로 비디오 카메라의 영상을 저장하는 프로그램을 만드는 것도 그리 어렵지 않다고 생각됩니다. 자. 한번 해보세요. 그리고 소스를 공개할 용의가 있는 분들은 함께 JMF를 시작하는 다른 분들에게도 정보를 나누어 주세요..어차피 기술은 공유되어야 더욱 더 발전됩니다. 혼자만 알고 있는 기술. 과연 그것이 자신만의 독보적인 핵심기술일까요.. 쩝.. 후후. 같이 열심히 하자는 이야기 입니다.


[알림]
여러분도 아시겠지만, 마이크로 소프트웨어 잡지의 2,3,4월호에도 JMF를 이용한 방송국 프로그램에 대한 강좌가 있더군요. 저도 읽어보았고 소스분석도 다 마쳤습니다. 일단은 목적이 인터넷 방송 선국장치를 통한 간략한 방송 프로그램의 작성이구요.. 네에.. 처음 JMF를 시작하시는 분들은 꼭 읽어보세요.. 자료도 별로 없을때 이렇게 연재를 시작한것은 정말 우리같은 개발자에게 도움이 됩니다. 아쉽다면 영상부분의 몇몇 설명을 그냥 건너뛴 점이구요.. 하여간 관심있는 분들 꼭 읽어보세요. 나중에 저도 시간나면 마이크로 소프트웨어의 JMF 강좌를 재 구성해서 괜찮은 프로그램 하나 만들어 올리도록 하죠.. 음.. 시간이 될라나 모르겠지만...


자. 이번 시간에는 Sun의 JMF 공식 홈페이지에 있는 Solution 예제중에서 우리에게 꽤나 필요한 프로그램인 Clone.java에 대해 알아보려고 합니다.
일단 먼저 소스 프로그램을 다운 받으시고, 실행해 보세요.. 

주어진 문제
DataSource로 부터 Source Clone을 생성하고, 미디어의 플레이백을 위해서 서로다른 Player를 생성한다. 

해결책
아래에 간단한 샘플 애플리케이션이 있습니다. 이것은 플레이백을 위한 입력 미디어의 URL을 실행인자로 받아들이고, 플레이백을 위해 얼마나 많은 복사본을 생성할지의 갯수를 받아들입니다. 실제 프로그램은 아래의 단계를 따라 수행됩니다. 

  1. 주어진 입력 URL을 통해서 DataSource를 생성하기 
  2. Manager.createCloneableDataSource를 이용해서 원본 DataSource로부터 cloneable DataSource를 생성하기 
  3. cloneable DataSource로부터 clone 생성하기 
  4. cloneable DataSource 와 각각 생성된 clones에 대하여 playback를 위한 player를 만들기 
 
  • 필요조건
  • 관련 클래스들 
  • 프로그램 구동 방법
  • 소스 코드
필요조건
Platform: JDK 1.1.6 or later
JMF API: 2.0 or later
Implementation: AJ, WPP, SPP *

* AJ = All Java, WPP = Windows Performance Pack, SPP = Solaris Performance Pack

관련클래스
  • javax.media.Player
  • javax.media.Manager
  • javax.media.protocol.SourceCloneable
프로그램 구동 방법
java Clone <URL> <# of copies>


Example:
java Clone file:/c:/temp/foo.mov 2
Source Code

위의 예제는 Sun의 JMF 홈페이지에서 보실 수 있습니다. 예제의 이름은 Clone.java인데, 아주 간단한 프로그램이지만, 실제로 전 이 프로그램에서 제공된 방법을 통해서 많은 부분 도움을 받고 있습니다. 처음 JMF 할때 도대체 데이타 복제를 어떻게 해야하나.. 여러개의 플레이어를 동시에 재생하려면 어떻게 해야하나하는 의문들이 들었었는데... 바로 이 소스 코드를 보고 해결할 수 있었습니다. 그래서 예제들도 무심히 지나치지 마시고, 반드시 숙독해서 자신의 프로그램에 바로바로 적용할 수 있도록 하는 것도 좋은 방법이라고 생각됩니다.

// Clone.java

// 요구되는 패키지들의 임포트부분 
import java.awt.*;
import javax.media.*;
import javax.media.control.TrackControl;
import javax.media.format.*;
import javax.media.protocol.*;

import java.net.*;
import java.io.*;

/**
* cloneable DataSource를 이용해서 실제 dataSource를 복제하고 그 결과로 playback을 수행하는 
* 애플리 케이션 입니다. 
* 이 프로그램은 Sun에서 제공된 예제 입니다.  
*/


// 데이타 소스의 복제를 위해 필요한 기능을 수행하는 클래스를 하나 만들었습니다.
// 이 클래스 내부에서 복제하고자 하는 데이타 소스를 인자로 넘겨받아서 Player를 생성하고 
// 생성된 Player에 대해 이벤트 처리를 하는 부분입니다.
// 주의 할것은, 단순히 player만 생성한후에 이벤트 처리와 함께 player의 states 처리를 제대로 하지 않으면
// 프로그램 구동후 얼마안가서 바로 해석하기도 힘든 에러가 발생한다는 점입니다. 
// 잊지 마세요.. 이벤트 처리 및 Player의 states 처리!!!

public class Clone extends Frame implements ControllerListener {

    Player p;        // Playback을 위한 Player

    Object waitSync = new Object();
    boolean stateTransitionOK = true;


    /**
    * 데이타소스가 주어지면, player를 생성하고, 생성된 player를 이용해서 
    * playback을 하기위해서 사용합니다. 
    */

    public boolean open(DataSource ds) {

   
    // 데이타소스의 타입이 어떠한 것인지를 먼저 알아봅니다. DataSource의 getContentType()를 이용합니다.
        // 이때 리턴되는 값은 데이타 소스의 미디어 타입에 대한 String 입니다.
        // 예를 들면 create player for: RAW 이와 같은 형태입니다.

        System.err.println("create player for: " + ds.getContentType());

        // player를 만들기 위해서 Manager의 createPlayer를 호출합니다.
        // 이때 넘겨주는 인자가 바로 데이타 소스 입니다. 
        try {
            p = Manager.createPlayer(ds);

        } catch (Exception e) {
            System.err.println("Failed to create a player from the given DataSource: " + e);
            return false;
        }

        // player의 생성이 성공했다면 player에 대한 이벤트 처리를 등록하여야 합니다.
        p.addControllerListener(this);


        // player를 Realize 단계까지 이동하도록 만들어 주어야 합니다.
        // 여기서 주의할것은 player를 생성한후 바로 start를 호출하지 말고 
        // 현재 player의 상태를 체크해서 각 상태에 알맞도록 처리를 해주어야 한다는 것입니다. 
        // player의 prefetch를 호출함으로서 player에게 prefetched 상태로 이동하도록 명령합니다.

        p.prefetch();

        // player가 원하는 상태에 도달되도록 기다립니다.
        if (!waitForState(p.Prefetched)) {
            System.err.println("Failed to realize the player.");
            return false;
        }

        // Realize 상태까지 완료되었다면 이제 우리는 이 부분에서 
        // VisualComponent와 ControlPanelComponent를 추가하여 사용자에게 시각적인 효과를 
        // 나타낼 수 있습니다. 
        // 이 부분에서는 일단 레이아웃을 변경했구요..
        setLayout(new BorderLayout());

        // visual component를 얻기위해서 선언했구요
        Component cc;

        // controlPanelComponent를 얻기 위해서 선언했습니다. 
        Component vc;
        if ((vc = p.getVisualComponent()) != null) {
            add("Center", vc);
        }

        if ((cc = p.getControlPanelComponent()) != null) {
            add("South", cc);
        }

        // 자. 여기까지 해서, 시각적인 컴포넌트의 등록까지 마쳤습니다.
        // 이제 남은것은 player를 start 시키는 일 입니다. 

        p.start();

        // 화면에 보이도록...
        setVisible(true);

        return true;
    }

    public void addNotify() {
        super.addNotify();
        pack();
    }

    /**
    * Player로 하여금 주어진 상태로 이동할때까지 Blocking을 합니다. 
    * 만약 player의 상태변화가실패하면 false가 리턴됩니다. 
    * 아래에 구현된 while에 의한 방법이 그래도 가장 안전한 방법이네요...
    */

    boolean waitForState(int state) {
        synchronized (waitSync) {
            try {
                while (p.getState() < state && stateTransitionOK)
                waitSync.wait();
            } catch (Exception e) {}
        }
        return stateTransitionOK;
    }


    /**
    * Controller에 대한 이벤트 리스터 부분입니다. 
    * 이 부분들은 예전부터 강좌에서 많이 설명드렸으니 어렵지 않죠??
    */
    public void controllerUpdate(ControllerEvent evt) {

        if (evt instanceof ConfigureCompleteEvent ||
            evt instanceof RealizeCompleteEvent ||
            evt instanceof PrefetchCompleteEvent) {
            synchronized (waitSync) {
                stateTransitionOK = true;
                waitSync.notifyAll();
            }
        } else if (evt instanceof ResourceUnavailableEvent) {
            synchronized (waitSync) {
                stateTransitionOK = false;
                waitSync.notifyAll();
            }
        } else if (evt instanceof EndOfMediaEvent) {
            p.close();
            //System.exit(0);
        } else if (evt instanceof SizeChangeEvent) {
        }
    }



    /**
    * Main program 부분입니다. 애플리케이션이니까 당근이죠..
    * main문의 인자로 플레이백을 위해 필요한 미디어 파일의 이름과 몇개의 데이타 소스를 
    * 복제할것인가에 대한 갯수를 넘겨주어야 합니다.
    */

    public static void main(String [] args) {

        if (args.length == 0) {
            prUsage();
            System.exit(0);
        }

        MediaLocator ml;
        int copies = 1;

        // 파일이름을 스트링형태로 받아서 MediaLocator를 생성합니다.
        if ((ml = new MediaLocator(args[0])) == null) {
            System.err.println("Cannot build media locator from: " + args[0]);
            prUsage();
            System.exit(0);
        }

        if (args.length > 1) {
        try {
            copies = new Integer(args[1]).intValue();
        } catch (NumberFormatException e) {
            System.err.println("An invalid # of copies is specified: " + args[1]);
            System.err.println("Will default to 1.");
            copies = 1;
        }
    }

    DataSource ds = null;

    // MediaLocator를 통해서 원하는 미디어 파일의 위치를 알아내었죠?
    // 이제 그렇게 알아낸 위치로부터 데이타 소스를 생성해 내야 합니다.
    // 바로 , Manager의 createDataSource를 호출합니다.
    // 물론 이때 넘겨주는 인자는 MediaLocator가 되겠지요..
    // 이 부분에 한 작업이 바로 원본 데이타소스를 만드는 과정이었구요..

    try {
        ds = Manager.createDataSource(ml);
    } catch (Exception e) {
        System.err.println("Cannot create DataSource from: " + ml);
        System.exit(0);
    }

    // 자. 이부분이 바로 데이타소스 복제의 핵심입니다.
    // Manager의 createCloneableDataSource를 이용해서 원본 데이터를 넘겨주면 
    // 원본 데이타소스에 대한 복제본 데이타 소스가 리턴되어 나옵니다.
    // 이 리턴된 복제본 데이타 소스를 이용해서 우리가 원하는 player를 만들고 playback을 하기위해서 
    // 위에서 만든 Clone 클래스로 복제본 데이타 소스를 넘겨주는 것입니다. 

    ds = Manager.createCloneableDataSource(ds);    // 정말 주의!! 이부분 확인하세요.. 아래에 정리했습니다. 

    if (ds == null) {
        System.err.println("Cannot clone the given DataSource");
        System.exit(0);
    }

    Clone clone = new Clone();


    // 복제본 데이타 소스 클래스는 위에서 만들었고, 복제된 데이타 소스를 넘겨줍니다.
   
// 이렇게 해서 player가 생성되도록 해야겠죠..
    
    if (!clone.open(ds))
        System.exit(0);

    // player를 여려개 만들려고 하는경우
    // 아래와 같이 루프를 돌려서 새롭게 player를 만들고 이벤트 처리를 위해서 
    // 원하는 갯수만큼 새롭게 Clone 클래스를 만들어 주어야 합니다. 

    for (int i = 1; i < copies; i++) {
        clone = new Clone();
        if (!clone.open(((SourceCloneable)ds).createClone()))
            System.exit(0);
        }
    }


    static void prUsage() {
        System.err.println("Usage: java Clone <url> <# of copies>");
    }
}

///////////////////// program End

SourceCloneable은 interface 로서, cloneable되어지는 경우에 반드시 implements되어야 합니다. 
cloneable DataSource를 생성하기 위해서는 Manager.createCloneableDataSource 를 이용해야 합니다.

 DataSource createClone()
          이 함수는 동일한 데이타 스트림의 복사본을 제공하기 위해 원본 DataSource의 clone을 생성하도록 해줍니다.
 

Method Detail

createClone

public DataSource createClone()
Create a clone of the original DataSource that provides a copy of the same data streams. The clones generated may or may not have the same properties of the original DataSource depending on the implementation. Therefore, they should be checked against the properties required for the application.
For example, the original DataSource may be a "pull" DataSource (PullDataSource or PullBufferDataSource). But the resulted clone may be the equivalent "push" DataSource. In that case, the resulting "push" DataSource will push data at the same rate at which the original DataSource is being pulled.
Returns:
a clone of the DataSource, or null if a clone could not be created.


createCloneableDataSource

public static DataSource createCloneableDataSource(DataSource source)
Creates a cloneable DataSource. The returned DataSource implements the SourceCloneable interface and enables the creation of clones by the createClone method.

If the input DataSource implements SourceCloneable, it will be returned right away as the result. Otherwise, a "proxy" DataSource is created. It implements the SourceCloneable interface and can be used to generate other clones.

[전 처음에 아랫부분 무시했다가 엄청 혼났습니다. 주의하세요.. ]
When createCloneableDataSource is called on a DataSource,
the returned DataSource should be used in place of the original DataSource.
Any attempt to use the original DataSource may generate unpredictable results.

The resulted cloneable DataSource can be used to generate clones.

The clones generated may or may not has the same properties of the original DataSource depending on the implementation. Therefore, they should be checked against the properties required for the application. If the original DataSource is not SourceCloneable and a "proxy" DataSource is resulted, the clones generated from this "proxy" DataSource is of type PushDataSource or PushBufferDataSource depending on the type of the original DataSource. In this case, each clone pushes data at the same rate that the original DataSource is pulled or pushed.
Parameters:
source - the DataSource to be cloned
Returns:
a cloneable DataSource for the given source

[정리]
그다지 어려운 소스 프로그래은 아닙니다만, 정말 중요한 내용이 많이 들어있었습니다. 그래서 특별히 이번소스를 분석해서 강좌에 넣게 되었구요. 이 부분에서 주의할 것은 원본 데이타 소스에 대해서 복제본을 만들기 위해서 Manager.createCloneableDataSource를 호출하였고, 리턴된 값이 바로 복제본 데이타 소스가 되는 것입니다. 이렇게 복제된 데이타 소스를 가지고, 원하는 갯수만큼의 player를 만들고 이벤트 처리를 하게 된것이지요.  현재 이 프로그램의 필요성이 없을런지는 몰라도..  아참. 바로 이전강좌에서도 제가 이 clone 클래스를 이용했거든요.. 기억이 나시나요? 한번 이전 강좌를 다시 읽어봐주세요..

또 하나 주의할 점은 Manager.createCloneableDataSource를 통해서 복제 가능한 데이타 소스를 생성했다면, 더 이상 원본 데이타 소스를 이용해서는 안되고, 원본 데이타 소스가 이용되는 부분에는 복제 가능한데이타 소스로 전부 바꾸어져야 한다는 것입니다. 실제로 제가 이것때문에 처음에 프로그램이 이유없이..(??) 다운되고, 시스템도 재부팅되고.. 하여간 정말 고생많았지요.. 언제나 도움말을 확실히 읽고 넘어가자구요.. 결국 도움말에 나와있더라구요.. 쩝...

 

[ 질문에 대한 답변]

아래 질문에 대한 답변은 함께 공유하면 좋을듯 싶어서... 올립니다. 지난 번에 어느분이 매일로 문의하신 내용인데요..

문의 : 제가 프로그램 돌릴때는 아래와 같은 에러 메시지만 나오고 프로그램이 중단됩니다. 예제는 Sun에서 다운로드 받은것도 있구요. 훈님의 강좌예제중에서 캡쳐해서 저장하는 예제도 아래와 같은 에러가 납니다.

Unable to realize com.sun.media.MediaEngine@62ac60a3 coudn't realize processor


답변: 사실 처음 프로그래밍할때 이런 에러가 나오면 정말 난감합니다. 도대체 이렇게 에러 메시지가 나오면 어디에서 찾아 보아야 하나요.. 쩝.. 그렇죠? 그런데 잘 보니까 MediaEngine 이라는 부분이 있네요.. 그리고 processor가 realize가 안되었다는 이야기이구요.. 사실 이것만 봐서는 어떤곳이 에러인지 정말 찾기가 어렵습니다. 그래서 프로그램 실행할때 생성되는 jmf.log 파일을 보내달라고 했습니다. 그래서 확인한 사항인데... 보내준 jmf.log 파일을 보니까... 주루루룩 설명이 있다가 아래와 같은 메시지가 있더군요..

## Connect to multiplexer
## Output content type : AVI

XX Failed to find a multiplexer for the specified output
XX Failed to realize : com.sun.media.MediaEngine@17c05de7
XX Cannot connect the multiplexer


자. 보셨나요.. 이곳에서도 MediaEngine 이라고 나옵니다. 그리고 그 밑에 processor가 realize되지 않는다고 나오지요. 그럼 그 윗부분을 보세요..  Connect to multiplexer부분에서 우리가 지정한 타입이 AVI 입니다. 즉, 예제 프로그램에서 AVI로 저장할 타입을 지정했는데.. 프로그램을 구동시키는 시스템에서는 특정타입을 AVI 변환해주는 Multiplexer를 찾을수 없다는 이야기입니다. 결국은 , 이러한 문제의 근본 원인은 우리가 프로그램에서 지정해준 압축 포맷이 프로세서의 CODEC에 의해서 인식되지 못한다는 점이지요.. 많은 분들이 윈도우 환경에서 AVI로 저장할때 이런 문제점을 많이 본다고 합니다. 이런 경우 결국은 프로그래머가 스스로 Codec을 만들던가( 좀 힘들겠죠?) 아니면 다른 파일포맷 (예를들어 .mov , .mpg)등으로 저장하도록 변경해야 합니다.
결국은 구동하는 시스템에 processor가 인식하는 multiplexer가 제대로 있는가의 문제입니다.

이부분에 대한 설명은 제 강좌의 JMFRegistry 부분에서도 설명이 되어 있습니다. 참조해보세요.


위의 그림에서 보는바와 같이 일단 원본 데이타소스인 A로부터 복제가능한 데이터소스인 B를 만들고 나면, A는 더이상 사용할 수가 없고, A가 필요한 자리에는 모두 B로 대치되어야 합니다. 이렇게 복제가능한 데이타 소스인 B가 만들어지면, 이 B를 가지고 player를 하나 만듭니다. 그 후에 2개의 player를 더 만들고 싶은경우, 원본 데이타 소스인 A를 이용하는 것이 아니라, 복제 가능한 데이타 소스인 B로부터 createClone 함수를 이용하여 계속해서 복제를 해서 사용해야 합니다.  주의하세요...

'java UI' 카테고리의 다른 글

quartz 를 이용하기  (0) 2008.01.22
File Connection Optiobal Package  (0) 2006.02.28
[펌] DataSource의 복제를 통한 다중 플레이어 생성방법  (0) 2005.12.02
jtable tutorial  (0) 2005.02.16
The Eclipse runtime options  (0) 2005.02.15
www.eclipse-plugins.info 의 순위  (0) 2005.02.12
Posted by 김용환 '김용환'

댓글을 달아 주세요

jtable tutorial

java UI 2005. 2. 16. 12:02

 

http://java.sun.com/docs/books/tutorial/uiswing/components/table.html

 

The JavaTM Tutorial

Previous Page Lesson Contents Next Page Start of Tutorial > Start of Trail > Start of Lesson Search
Feedback Form

Trail: Creating a GUI with JFC/Swing
Lesson: Using Swing Components

How to Use Tables

With the JTable (in the API reference documentation) class you can display tables of data, optionally allowing the user to edit the data. JTable doesn't contain or cache data; it's simply a view of your data. Here's a picture of a typical table displayed within a scroll pane:

A snapshot of TableDemo, which displays a typical table.

[PENDING: Update this snapshot.
Label these parts:
- each cell displays an item of data
- each column header describes its column
maybe also have these labels: 
- each column contains one type of data
- a table header displays the column headers]

The rest of this section tells you how to accomplish some common table-related tasks. Here are the topics this section covers:

Creating a Simple Table

A snapshot of SimpleTableDemo, which displays a simple table.

[PENDING: This figure will be updated.]

Try this: 
  1. Run SimpleTableDemo using JavaTM Web Start (in the Creating a GUI with JFC/Swing trail). Or, to compile and run the example yourself, consult the example index.
  2. Click the cell that contains "Snowboarding".
    The entire first row is selected, indicating that you have selected Mary Campione's data. A special highlight indicates that the "Snowboarding" cell is editable. Generally, you begin editing a text cell by double-clicking it.
  3. Position the cursor over "First Name". Now press the mouse button and drag to the right.
    As you can see, users can rearrange columns in tables.
  4. Position the cursor just to the right of a column header. Now press the mouse button and drag to the right or left.
    The column changes size, and the other columns adjust to fill the remaining space.
  5. Resize the window containing the table so that it's bigger than necessary to display the whole table.
    All the table cells become wider, expanding to fill the extra horizontal space.

Here is the code that implements the table in SimpleTableDemo.java (in a .java source file):
String[] columnNames = {"First Name",
                        "Last Name",
                        "Sport",
                        "# of Years",
                        "Vegetarian"};

Object[][] data = {
    {"Mary", "Campione",
     "Snowboarding", new Integer(5), new Boolean(false)},
    {"Alison", "Huml",
     "Rowing", new Integer(3), new Boolean(true)},
    {"Kathy", "Walrath",
     "Knitting", new Integer(2), new Boolean(false)},
    {"Sharon", "Zakhour",
     "Speed reading", new Integer(20), new Boolean(true)},
    {"Philip", "Milne",
     "Pool", new Integer(10), new Boolean(false)}
};

JTable table = new JTable(data, columnNames);
The SimpleTableDemo example uses one of two JTable constructors that directly accept data:
  • JTable(Object[][] rowData, Object[] columnNames)
  • JTable(Vector rowData, Vector columnNames)
The advantage of these constructors is that they're easy to use. However, these constructors also have disadvantages:
  • They automatically make every cell editable.
  • They treat all data types the same (as strings). For example, if a table column has Boolean data, the table can display the data in a check box. However, if you use one of the two JTable constructors listed previously, your Boolean data will be displayed as a string. You can see this difference in the last column of the two previous pictures of tables.
  • They require that you put all of the table's data in an array or vector, which isn't appropriate for some data. For example, if you're instantiating a set of objects from a database, you might want to query the objects directly for their values, rather than copying all their values into an array or vector.
If you want to get around these restrictions, you need to implement your own table model, as described in Creating a Table Model.

Adding a Table to a Container

It's easy to put a table in a scroll pane. You need just one or two lines of code:
JScrollPane scrollPane = new JScrollPane(table);
table.setPreferredScrollableViewportSize(new Dimension(500, 70));
The scroll pane automatically gets the table's header, which displays the column names, and puts it on top of the table. Even when the user scrolls down, the column names remain visible at the top of the viewing area. The scroll pane also tries to make its viewing area the same as the table's preferred viewing size. The previous code snippet sets the table's preferred viewing size with the setPreferredScrollableViewportSize method.

If you're using a table without a scroll pane, then you must get the table header component and place it yourself. For example:

container.setLayout(new BorderLayout());
container.add(table.getTableHeader(), BorderLayout.PAGE_START);
container.add(table, BorderLayout.CENTER);

Setting and Changing Column Widths

By default, all columns in a table start out with equal width, and the columns automatically fill the entire width of the table. When the table becomes wider or narrower (which might happen when the user resizes the window containing the table), all the column widths change appropriately.

When the user resizes a column by dragging its right border, then either other columns must change size, or the table's size must change. By default, the table's size remains the same, and all columns to the right of the drag point resize to accommodate space added to or removed from the column to the left of the drag point.

The following figures illustrate the default resizing behavior. [PENDING: These will be updated.]

SimpleTableDemo
Initially, the columns have equal width.

SimpleTableDemo during resizing
When the user resizes a column, some of the other columns must adjust size for the table to stay the same size.

SimpleTableDemo after the entire table is resized
When the entire table is resized, all the columns are resized.

To customize initial column widths, you can invoke setPreferredWidth on each of your table's columns. This sets both the preferred widths of the columns and their approximate relative widths. For example, adding the following code to SimpleTableDemo makes its third column bigger than the other columns:

TableColumn column = null;
for (int i = 0; i < 5; i++) {
    column = table.getColumnModel().getColumn(i);
    if (i == 2) {
        column.setPreferredWidth(100); //sport column is bigger
    } else {
        column.setPreferredWidth(50);
    }
}

As the preceding code shows, each column in a table is represented by a TableColumn (in the API reference documentation) object. TableColumn supplies getter and setter methods for the minimum, preferred, and maximum widths of a column, as well as a method for getting the current width. For an example of setting cell widths based on the actual amount of space needed to draw the cells' contents, see the initColumnSizes method in TableRenderDemo.java (in a .java source file).

When the user explicitly resizes columns, the columns' preferred widths are set such that the user-specified sizes become the columns' new current widths. However, when table itself is resized — typically because the window has resized — the columns' preferred widths do not change. Instead, the existing preferred widths are used to calculate new column widths to fill the available space.

You can change a table's resize behavior by invoking the setAutoResizeMode method. The method's argument should have one of these values (defined as constants in JTable):

AUTO_RESIZE_SUBSEQUENT_COLUMNS
The default. In addition to resizing the column to the left of the drag point, adjusts the sizes of all columns to the right of the drag point.
AUTO_RESIZE_NEXT_COLUMN
Adjusts only the columns immediately to the left and right of the drag point.
AUTO_RESIZE_OFF
Adjusts the table size instead.

Detecting User Selections

The following code snippet shows how to detect when the user selects a table row. By default, a table allows the user to select multiple rows — not columns or individual cells — and the selected rows need not be next to each other. Using the setSelectionMode method, the following code specifies that only one row at a time can be selected.
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
...
//Ask to be notified of selection changes.
ListSelectionModel rowSM = table.getSelectionModel();
rowSM.addListSelectionListener(new ListSelectionListener() {
    public void valueChanged(ListSelectionEvent e) {
        //Ignore extra messages.
        if (e.getValueIsAdjusting()) return;

        ListSelectionModel lsm =
            (ListSelectionModel)e.getSource();
        if (lsm.isSelectionEmpty()) {
            ...//no rows are selected
        } else {
            int selectedRow = lsm.getMinSelectionIndex();
            ...//selectedRow is selected
        }
    }
});
The code is from SimpleTableSelectionDemo.java (in a .java source file). SimpleTableSelectionDemo also has code (not included in the preceding snippet) that changes the table's selection orientation. By changing a couple of boolean values, you can make the table allow either column selections or individual cell selections, instead of row selections.

For more information and examples of implementing selection, see How to Write a List Selection Listener.

Creating a Table Model

As the following figure shows, every table gets its data from an object that implements the TableModel (in the API reference documentation) interface.

TableDemo

[PENDING: This figure might be updated to look more modern.]

The JTable constructor used by SimpleTableDemo creates its table model with code like this:

new AbstractTableModel() {
    public String getColumnName(int col) {
        return columnNames[col].toString();
    }
    public int getRowCount() { return rowData.length; }
    public int getColumnCount() { return columnNames.length; }
    public Object getValueAt(int row, int col) {
        return rowData[row][col];
    }
    public boolean isCellEditable(int row, int col)
        { return true; }
    public void setValueAt(Object value, int row, int col) {
        rowData[row][col] = value;
        fireTableCellUpdated(row, col);
    }
}
As the preceding code shows, implementing a table model can be simple. Generally, you implement your table model in a subclass of the AbstractTableModel (in the API reference documentation) class.

Your model might hold its data in an array, vector, or hash map, or it might get the data from an outside source such as a database. It might even generate the data at execution time.

Here again is a picture of a table implemented by TableDemo (which you can run using Java Web Start (in the Creating a GUI with JFC/Swing trail)) that has a custom table model:

A snapshot of TableDemo. Again.

[PENDING: This figure will be updated.]

This table is different from the SimpleTableDemo table in the following ways:

  • TableDemo's custom table model, even though it's simple, can easily determine the data's type, helping the JTable display the data in the best format. SimpleTableDemo's automatically created table model, on the other hand, isn't smart enough to know that the # of Years column contains numbers (which should generally be right aligned and have a particular format). It also doesn't know that the Vegetarian column contains boolean values, which can be represented by check boxes.
  • In TableDemo, we implemented the custom table model so that it doesn't let you edit the name columns; it does, however, let you edit the other columns. In SimpleTableDemo, all cells are editable.

Below is the code from TableDemo.java (in a .java source file) that is different from the code in SimpleTableDemo.java (in a .java source file). Bold font indicates the code that makes this table's model different from the table model defined automatically for SimpleTableDemo.

public TableDemo() {
    ...
    JTable table = new JTable(new MyTableModel());
    ...
}

class MyTableModel extends AbstractTableModel {
    private String[] columnNames = ...//same as before...
    private Object[][] data = ...//same as before...

    public int getColumnCount() {
        return columnNames.length;
    }

    public int getRowCount() {
        return data.length;
    }

    public String getColumnName(int col) {
        return columnNames[col];
    }

    public Object getValueAt(int row, int col) {
        return data[row][col];
    }

    public Class getColumnClass(int c) {
        return getValueAt(0, c).getClass();
    }

    /*
     * Don't need to implement this method unless your table's
     * editable.
     */
    public boolean isCellEditable(int row, int col) {
        //Note that the data/cell address is constant,
        //no matter where the cell appears onscreen.
        if (col < 2) {
            return false;
        } else {
            return true;
        }
    }

    /*
     * Don't need to implement this method unless your table's
     * data can change.
     */
    public void setValueAt(Object value, int row, int col) {
        data[row][col] = value;
        fireTableCellUpdated(row, col);
    }
    ...
}

Detecting Data Changes

A table and its model automatically detect whenever the user edits the table's data. However, if the data changes for another reason, you must take special steps to notify the table and its model of the data change. Also, if you don't implement a table model, as in SimpleTableDemo, then you must take special steps to find out when the user edits the table's data.

An example of updating a table's data without directly editing it is in the BINGO application. The BINGO application, which is presented in BINGO! (in the Creating a GUI with JFC/Swing trail), has a table that displays some information about each user who is signed up to play the game. When a new user signs up to play BINGO, the table needs to add a new row for that user. More precisely, the table model needs to get the data for the new user, and then the table model needs to tell the table to display the new data.

To notify the table model about a new user, the BINGO application invokes the table model's updatePlayer method. You can see the code for that method in PlayerInfoModel (in a .java source file), which contains the implementation of the table model. The updatePlayer method records the new user's data and fires a table-model event. Because every table listens for table-model events from its model, the user-information table automatically detects the change and displays the new data.

To fire the table-model event, the model invokes the fireTableRowsInserted method, which is defined by the AbstractTableModel class. Other fireXxxx methods that AbstractTableModel defines are fireTableCellUpdated, fireTableChanged, fireTableDataChanged, fireTableRowsDeleted, fireTableRowsInserted, fireTableRowsUpdated, and fireTableStructureChanged.

If you have a class such as SimpleTableDemo that isn't a table or table model, but needs to react to changes in a table model, then you need to do something special to find out when the user edits the table's data. Specifically, you need to register a TableModelListener (in the API reference documentation) on the table model. Adding the bold code in the following snippet makes SimpleTableDemo react to table data changes.

import javax.swing.event.*;
import javax.swing.table.TableModel;

public class SimpleTableDemo ... implements TableModelListener {
    ...
    public SimpleTableDemo() {
        ...
        table.getModel().addTableModelListener(this);
        ...
    }

    public void tableChanged(TableModelEvent e) {
        int row = e.getFirstRow();
        int column = e.getColumn();
        TableModel model = (TableModel)e.getSource();
        String columnName = model.getColumnName(column);
        Object data = model.getValueAt(row, column);

        ...// Do something with the data...
    }
    ...
}

Concepts: Editors and Renderers

Before you go on to the next few tasks, you need to understand how tables draw their cells. You might expect each cell in a table to be a component. However, for performance reasons, Swing tables aren't implemented that way.

Instead, a single cell renderer is generally used to draw all of the cells that contain the same type of data. You can think of the renderer as a configurable ink stamp that the table uses to stamp appropriately formatted data onto each cell. When the user starts to edit a cell's data, a cell editor takes over the cell, controlling the cell's editing behavior.

For example, each cell in the # of Years column in TableDemo contains Number data — specifically, an Integer object. By default, the cell renderer for a Number-containing column uses a single JLabel instance to draw the appropriate numbers, right-aligned, on the column's cells. If the user begins editing one of the cells, the default cell editor uses a right-aligned JTextField to control the cell editing.

To choose the renderer that displays the cells in a column, a table first determines whether you specified a renderer for that particular column. (We'll tell you how to specify renderers a bit later.) If you didn't, then the table invokes the table model's getColumnClass method, which gets the data type of the column's cells. Next, the table compares the column's data type with a list of data types for which cell renderers are registered. This list is initialized by the table, but you can add to it or change it. Currently, tables put the following types of data in the list:

  • Boolean — rendered with a check box.
  • Number — rendered by a right-aligned label.
  • Double, Float — same as Number, but the object-to-text translation is performed by a NumberFormat (in the API reference documentation) instance (using the default number format for the current locale).
  • Date — rendered by a label, with the object-to-text translation performed by a DateFormat (in the API reference documentation) instance (using a short style for the date and time).
  • ImageIcon, Icon — rendered by a centered label.
  • Object — rendered by a label that displays the object's string value.

Version note: The default renderer associations for Double, Float, and Icon were added in 1.3.

Cell editors are chosen using a similar algorithm.

Remember that if you let a table create its own model, it uses Object as the type of every column. To specify more precise column types, the table model must define the getColumnClass method appropriately, as demonstrated by TableDemo.java (in a .java source file).

Keep in mind that although renderers determine how each cell or column header looks and can specify its tool tip text, renderers don't handle events. If you need to pick up the events that take place inside a table, the technique you use varies by the sort of event you're interested in:

Situation How to Get Events
To detect events from a cell that's being edited... Use the cell editor (or register a listener on the cell editor).
To detect row/column/cell selections and deselections... Use a selection listener as described in Detecting User Selections.
To detect mouse events on a column header... Register the appropriate type of mouse listener  (in the Creating a GUI with JFC/Swing trail) on the table's JTableHeader object. (See TableSorter.java (in a .java source file) for an example.)
To detect other events... Register the appropriate listener on the JTable object.

The next few sections tell you how to customize display and editing by specifying renderers and editors. You can specify cell renderers and editors either by column or by data type.

Using a Combo Box as an Editor

Setting up a combo box as an editor is simple, as the following example shows. The bold line of code sets up the combo box as the editor for a specific column.
TableColumn sportColumn = table.getColumnModel().getColumn(2);
...
JComboBox comboBox = new JComboBox();
comboBox.addItem("Snowboarding");
comboBox.addItem("Rowing");
comboBox.addItem("Chasing toddlers");
comboBox.addItem("Speed reading");
comboBox.addItem("Teaching high school");
comboBox.addItem("None");
sportColumn.setCellEditor(new DefaultCellEditor(comboBox));
Here is a picture of the combo box editor in use:

A combo box cell editor in use

[PENDING: This figure will be updated. It should probably include the cursor.]

The preceding code is from TableRenderDemo.java (in a .java source file). You can run TableRenderDemo using Java Web Start (in the Creating a GUI with JFC/Swing trail).

Using an Editor to Validate User-Entered Text

If a cell's default editor allows text entry, you get some error checking for free if the cell's type is specified as something other than String or Object. The error checking is a side effect of converting the entered text into an object of the proper type.

Version note: Before 1.3, the default implementation did not in any way restrict the string that could be entered, and didn't convert it from a String. You needed to put some ugly code in the model's setValueAt method to parse the entered string and prevent the cell's value from becoming a String.

The automatic checking of user-entered strings occurs when the default editor attempts to create a new instance of the class associated with the cell's column. The default editor creates this instance using a constructor that takes a String as an argument. For example, in a column whose cells have type Integer, when the user types in "123" the default editor creates the corresponding Integer using code equivalent to new Integer("123"). If the constructor throws an exception, the cell's outline turns red and refuses to let focus move out of the cell. If you implement a class used as a column data type, you can use the default editor if your class supplies a constructor that takes a single argument of type String.

If you like having a text field as the editor for a cell, but want to customize it — perhaps to check user-entered text more strictly or to react differently when the text is invalid — you can change the cell editor to use a formatted text field. The formatted text field can check the value either continuously while the user is typing or after the user has indicated the end of typing (such as by pressing Enter).

The following code, taken from a demo named TableFTFEditDemo, sets up a formatted text field as an editor that limits all integer values to be between 0 and 100. You can run TableFTFEditDemo using Java Web Start (in the Creating a GUI with JFC/Swing trail). The following code makes the formatted text field the editor for all columns that contain data of type Integer.

table.setDefaultEditor(Integer.class,
                       new IntegerEditor(0, 100));
The IntegerEditor class is implemented as a subclass of DefaultCellEditor (in the API reference documentation) that uses a JFormattedTextField instead of the JTextField that DefaultCellEditor supports. It accomplishes this by first setting up a formatted text field to use an integer format and have the specified minimum and maximum values, using the API described in How to Use Formatted Text Fields. It then overrides the DefaultCellEditor implementation of the getTableCellEditorComponent, getCellEditorValue, and stopCellEditing methods, adding the operations that are necessary for formatted text fields.

The override of getTableCellEditorComponent sets the formatted text field's value property (and not just the text property it inherits from JTextField) before the editor is shown. The override of getCellEditorValue keeps the cell value as an Integer, rather than, say, the Long value that the formatted text field's parser tends to return. Finally, overriding stopCellEditing lets us check whether the text is valid, possibly stopping the editor from being dismissed. If the text isn't valid, our implementation of stopCellEditing puts up a dialog that gives the user the option of continuing to edit or reverting to the last good value. The source code is a bit too long to include here, but you can find it in IntegerEditor.java (in a .java source file).

Using Other Editors

Whether you're setting the editor for a single column of cells (using the TableColumn setCellEditor method) or for a specific type of data (using the JTable setDefaultEditor method), you specify the editor using an argument that adheres to the TableCellEditor interface. Fortunately, the DefaultCellEditor class implements this interface and provides constructors to let you specify an editing component that's a JTextField, JCheckBox, or JComboBox. You usually don't have to explicitly specify a check box as an editor, since columns with Boolean data automatically use a check box renderer and editor.

What if you want to specify an editor that isn't a text field, check box, or combo box? Well, because DefaultCellEditor doesn't support other types of components, you must do a little more work. You need to create a class that implements the TableCellEditor (in the API reference documentation) interface. The AbstractCellEditor (in the API reference documentation) class is a good superclass to use. It implements TableCellEditor's superinterface, CellEditor (in the API reference documentation), saving you the trouble of implementing the event firing code necessary for cell editors.

Your cell editor class needs to define at least two methods — getCellEditorValue and getTableCellEditorComponent. The getCellEditorValue method, required by CellEditor, returns the cell's current value. The getTableCellEditorComponent method, required by TableCellEditor, should configure and return the component that you want to use as the editor.


Version note: The AbstractCellEditor class was added in 1.3. Before then, implementing a cell editor for a new component type was much more difficult, since you had to implement all the CellEditor methods yourself.

Here is a picture of a table with a dialog that serves, indirectly, as a cell editor. When the user begins editing a cell in the Favorite Color column, a button (the true cell editor) appears and brings up the dialog, with which the user can choose a different color.

The cell editor brings up a dialog

[PENDING: This figure will be updated.]

You can run TableDialogEditDemo using Java Web Start (in the Creating a GUI with JFC/Swing trail), or compile and run it yourself by consulting the example index. Here is the code, taken from ColorEditor.java (in a .java source file), that implements the cell editor.

public class ColorEditor extends AbstractCellEditor
                         implements TableCellEditor,
                                    ActionListener {
    Color currentColor;
    JButton button;
    JColorChooser colorChooser;
    JDialog dialog;
    protected static final String EDIT = "edit";

    public ColorEditor() {
        button = new JButton();
        button.setActionCommand(EDIT);
        button.addActionListener(this);
        button.setBorderPainted(false);

        //Set up the dialog that the button brings up.
        colorChooser = new JColorChooser();
        dialog = JColorChooser.createDialog(button,
                                        "Pick a Color",
                                        true,  //modal
                                        colorChooser,
                                        this,  //OK button handler
                                        null); //no CANCEL button handler
    }

    public void actionPerformed(ActionEvent e) {
        if (EDIT.equals(e.getActionCommand())) {
            //The user has clicked the cell, so
            //bring up the dialog.
            button.setBackground(currentColor);
            colorChooser.setColor(currentColor);
            dialog.setVisible(true);

            fireEditingStopped(); //Make the renderer reappear.

        } else { //User pressed dialog's "OK" button.
            currentColor = colorChooser.getColor();
        }
    }

    //Implement the one CellEditor method that AbstractCellEditor doesn't.
    public Object getCellEditorValue() {
        return currentColor;
    }

    //Implement the one method defined by TableCellEditor.
    public Component getTableCellEditorComponent(JTable table,
                                                 Object value,
                                                 boolean isSelected,
                                                 int row,
                                                 int column) {
        currentColor = (Color)value;
        return button;
    }
}
As you can see, the code is pretty simple. The only part that's a bit tricky is the call to fireEditingStopped at the end of the editor button's action handler. Without this call, the editor would remain active, even though the modal dialog is no longer visible. The call to fireEditingStopped lets the table know that it can deactivate the editor, letting the cell be handled by the renderer again.

Using Custom Renderers

This section tells you how to create and specify a cell renderer. You can set a type-specific cell renderer using the JTable method setDefaultRenderer. To specify that cells in a particular column should use a renderer, you use the TableColumn method setCellRenderer. You can even specify a cell-specific renderer by creating a JTable subclass, as we'll show later.

It's easy to customize the text or image rendered by the default renderer, DefaultTableCellRenderer. You just create a subclass and implement the setValue method so that it invokes setText or setIcon with the appropriate string or image. For example, here is how the default date renderer is implemented:

static class DateRenderer extends DefaultTableCellRenderer {
    DateFormat formatter;
    public DateRenderer() { super(); }

    public void setValue(Object value) {
        if (formatter==null) {
            formatter = DateFormat.getDateInstance();
        }
        setText((value == null) ? "" : formatter.format(value));
    }
}

If extending DefaultTableCellRenderer doesn't do the trick, you can build a renderer using another superclass. The easiest way is to create a subclass of an existing component, making your subclass implement the TableCellRenderer (in the API reference documentation) interface. TableCellRenderer requires just one method: getTableCellRendererComponent. Your implementation of this method should set up the rendering component to reflect the passed-in state, and then return the component.

In the preceding snapshot of TableDialogEditDemo, the renderer used for Favorite Color cells is a subclass of JLabel called ColorRenderer. Here are excerpts from ColorRenderer.java (in a .java source file) that show how it's implemented.

public class ColorRenderer extends JLabel
                           implements TableCellRenderer {
    ...
    public ColorRenderer(boolean isBordered) {
        this.isBordered = isBordered;
        setOpaque(true); //MUST do this for background to show up.
    }

    public Component getTableCellRendererComponent(
                            JTable table, Object color,
                            boolean isSelected, boolean hasFocus,
                            int row, int column) {
        Color newColor = (Color)color;
        setBackground(newColor);
        if (isBordered) {
            if (isSelected) {
                ...
                //selectedBorder is a solid border in the color
                //table.getSelectionBackground().
                setBorder(selectedBorder);
            } else {
                ...
                //unselectedBorder is a solid border in the color
                //table.getBackground().
                setBorder(unselectedBorder);
            }
        }
        
        setToolTipText(...); //Discussed in the following section
        return this;
    }
}
Here is the code from TableDialogEditDemo.java (in a .java source file) that registers a ColorRenderer instance as the default renderer for all Color data:
table.setDefaultRenderer(Color.class, new ColorRenderer(true));

The next section shows a couple of examples of using TableColumn's setCellRenderer method, so we'll skip that for now and show you how to specify a renderer for a particular cell. To specify a cell-specific renderer, you need to define a JTable subclass that overrides the getCellRenderer method. For example, the following code makes the first cell in the first column of the table use a custom renderer:

TableCellRenderer weirdRenderer = new WeirdRenderer();
table = new JTable(...) {
    public TableCellRenderer getCellRenderer(int row, int column) {
        if ((row == 0) && (column == 0)) {
            return weirdRenderer;
        }
        // else...
        return super.getCellRenderer(row, column);
    }
};

Specifying Tool Tips for Cells

By default, the tool tip text displayed for a table cell is determined by the cell's renderer. However, sometimes it can be simpler to specify tool tip text by overriding JTable's implementation of the getToolTipText(MouseEvent) method. This section tells you how to use both techniques.

To add a tool tip to a cell using its renderer, you first need to get or create the cell renderer. Then, after making sure the rendering component is a JComponent, invoke the setToolTipText method on it.

An example of setting tool tips for cells is in TableRenderDemo, which you can run using Java Web Start (in the Creating a GUI with JFC/Swing trail). The source code is in TableRenderDemo.java (in a .java source file). It adds tool tips to the cells of the Sport column with the following code:

//Set up tool tips for the sport cells.
DefaultTableCellRenderer renderer =
        new DefaultTableCellRenderer();
renderer.setToolTipText("Click for combo box");
sportColumn.setCellRenderer(renderer);
Here is a picture of the resulting tool tip:

[PENDING: We will put a picture here. It might be cropped to just include the relevant cell and its tool tip (along with whatever other cells are between them).]

Although the tool tip text in the previous example is static, you can also implement tool tips whose text changes depending on the state of the cell or program. Here are a couple ways to do so:

  • Add a bit of code to the renderer's implementation of the getTableCellRendererComponent method.
  • Override the JTable method getToolTipText(MouseEvent).

An example of adding code to a cell renderer is in TableDialogEditDemo (which you can run using Java Web Start (in the Creating a GUI with JFC/Swing trail)). TableDialogEditDemo uses a renderer for colors, implemented in ColorRenderer.java (in a .java source file), that sets the tool tip text using the boldface code in the following snippet:

public class ColorRenderer extends JLabel 
                           implements TableCellRenderer {
    ...
    public Component getTableCellRendererComponent(
                            JTable table, Object color,
                            boolean isSelected, boolean hasFocus,
                            int row, int column) {
        Color newColor = (Color)color;
        ...
        setToolTipText("RGB value: " + newColor.getRed() + ", "
                                     + newColor.getGreen() + ", "
                                     + newColor.getBlue());
        return this;
    }
}
Here is an example of what the tool tip looks like:

TableDialogEditDemo with a tool tip describing the moused-over cell's RGB value

[PENDING: this snapshot needs to be updated. It should probably be cropped, as well.]

As we mentioned before, you can specify tool tip text by overriding JTable's getToolTipText(MouseEvent) method. The program TableToolTipsDemo shows how. You can run TableToolTipsDemo using Java Web Start (in the Creating a GUI with JFC/Swing trail). The cells with tool tips are in the Sport and Vegetarian columns. Here's are pictures of their tool tips:

[PENDING: put a picture here. It could be cropped to just include the relevant cell and its tool tip (along with whatever other cells are between them).]

TableToolTipsDemo with a tool tip for a cell in the Vegetarian column

[PENDING: this snapshot needs to be updated and cropped.]

Here is the code from TableToolTipsDemo.java (in a .java source file) that implements tool tips for cells in the Sport and Vegetarian columns:

JTable table = new JTable(new MyTableModel()) {    
    //Implement table cell tool tips.
    public String getToolTipText(MouseEvent e) {
        String tip = null;
        java.awt.Point p = e.getPoint();
        int rowIndex = rowAtPoint(p);
        int colIndex = columnAtPoint(p);
        int realColumnIndex = convertColumnIndexToModel(colIndex);

        if (realColumnIndex == 2) { //Sport column
            tip = "This person's favorite sport to "
                   + "participate in is: "
                   + getValueAt(rowIndex, colIndex);

        } else if (realColumnIndex == 4) { //Veggie column
            TableModel model = getModel();
            String firstName = (String)model.getValueAt(rowIndex,0);
            String lastName = (String)model.getValueAt(rowIndex,1);
            Boolean veggie = (Boolean)model.getValueAt(rowIndex,4);
            if (Boolean.TRUE.equals(veggie)) {
                tip = firstName + " " + lastName
                      + " is a vegetarian";
            } else {
                tip = firstName + " " + lastName
                      + " is not a vegetarian";
            }

        } else { //another column
            //You can omit this part if you know you don't 
            //have any renderers that supply their own tool 
            //tips.
            tip = super.getToolTipText(e);
        }
        return tip;
    }
    ...
}
The code is fairly straightforward, except perhaps for the call to convertColumnIndexToModel. That call is necessary because if the user moves the columns around, the view's index for the column doesn't match the model's index for the column. For example, the user might drag the Vegetarian column (which the model considers to be at index 4) so it's displayed as the first column — at view index 0. Since prepareRenderer gives us the view index, we need to translate the view index to a model index so we can be sure we're dealing with the intended column.

Specifying Tool Tips for Column Headers

You can add a tool tip to a column header by setting the tool tip text for the table's JTableHeader. Often, different column headers require different tool tip text. You can change the text by overriding the table header's getToolTipText(MouseEvent) method.

An example of using the same tool tip text for all column headers is in TableSorterDemo. Here is how it sets the tool tip text:

table.getTableHeader().setToolTipText(
        "Click to sort; Shift-Click to sort in reverse order");

TableToolTipsDemo has an example of implementing column header tool tips that vary by column. If you run TableToolTipsDemo, which you can do using Java Web Start (in the Creating a GUI with JFC/Swing trail), you'll see the tool tips when you mouse over any column header except for the first two. We elected not to supply tool tips for the name columns since they seemed self explanatory. (Actually, we just wanted to show you that it could be done.) Here's a picture of one of the column header tool tips:

TableToolTipsDemo with a tool tip for a column header

[PENDING: this snapshot needs to be updated. It should also be cropped.]

The following code implements the tool tips. Basically, it creates a subclass of JTableHeader that overrides the getToolTipText(MouseEvent) method so that it returns the text for the current column. To associate the revised table header with the table, the JTable method createDefaultTableHeader is overridden so that it returns an instance of the JTableHeader subclass.

protected String[] columnToolTips = {
    null,
    null,
    "The person's favorite sport to participate in",
    "The number of years the person has played the sport",
    "If checked, the person eats no meat"};
...

JTable table = new JTable(new MyTableModel()) {
    ...

    //Implement table header tool tips.
    protected JTableHeader createDefaultTableHeader() {
        return new JTableHeader(columnModel) {
            public String getToolTipText(MouseEvent e) {
                String tip = null;
                java.awt.Point p = e.getPoint();
                int index = columnModel.getColumnIndexAtX(p.x);
                int realIndex = 
                        columnModel.getColumn(index).getModelIndex();
                return columnToolTips[realIndex];
            }
        };
    }
};

Version note: Before 1.3, each column had its own header renderer, and you could use the value returned by the TableColumn method getHeaderRenderer to set a tool tip for a specific column header. For performance reasons, the default behavior is now to use a single renderer for all column headers, and getHeaderRenderer returns null. The default header renderer used for all columns is returned by the TableHeader method getDefaultRenderer, which was added in 1.3.

Sorting and Otherwise Manipulating Data

One way to perform data manipulation such as sorting is to use one or more specialized table models (data manipulators), in addition to the table model that provides the data (the data model). The data manipulators should sit between the table and the data model, as the following picture shows:

A data manipulator sits between a table and its model.

[PENDING: This figure will be updated.]

If you decide to implement a data manipulator, take a look at TableMap.java (in a .java source file) and TableSorter.java (in a .java source file). The TableMap class implements TableModel and serves as a superclass for data manipulators. TableSorter is a data manipulator that sorts the data provided by another table model. It used to be implemented as a subclass of TableMap, but now is a direct subclass of AbstractTableModel. You can use TableSorter as-is to provide sorting functionality, or you can use either TableSorter or TableMap as a basis for writing your own data manipulator.

To implement sorting with TableSorter, you need just three lines of code. The following listing shows the differences between TableDemo and its sorting cousin, TableSorterDemo.java (in a .java source file).

TableSorter sorter = new TableSorter(new MyTableModel()); //ADDED THIS
//JTable table = new JTable(new MyTableModel());          //OLD
JTable table = new JTable(sorter);             //NEW
sorter.setTableHeader(table.getTableHeader()); //ADDED THIS

Note: The TableSorter class was updated in February, 2004. We recommend the newer version, as it has more features and fixes several bugs. If you currently use the old version, you can update to the new one by deleting TableMap.java and making the following change in the code that sets up the sorter:
//sorter.addMouseListenerToHeaderInTable(table); //OLD
sorter.setTableHeader(table.getTableHeader());   //NEW

The setTableHeader method sets up the table's column headers to detect user clicks and update the UI appropriately. When the user clicks, the sorter sorts the rows based on the clicked column. As the following snapshot shows, when you click "Last Name", the rows are reordered so that the row with "Campione" becomes the first row.

TableSorterDemo after clicking Last Name

[PENDING: This figure will be updated.]

You can add secondary sorting by Control-clicking additional columns. For example, by clicking the Vegetarian column and then Control-clicking the Last Name column, you get an alphabetized listing of vegetarians followed by an alphabetized listing of omnivores.

[PENDING: We will add a figure showing secondary sorting.]

You can change the clicking behavior by reimplementing the MouseHandler class defined in TableSorter.java.

The Table API

The tables in this section cover just part of the table API. For more information about the table API, see the API documentation for JTable (in the API reference documentation) and for the various classes and interfaces in the table package (in the API reference documentation). Also see The JComponent Class, which describes the API that JTable inherits from JComponent. The API for using tables falls into the following categories:

Table-Related Classes and Interfaces
Class or Interface Purpose
JTable The component that presents the table to the user.
JTableHeader The component that presents the column names to the user. By default, the table generates this component automatically.
TableModel
AbstractTableModel
Respectively, the interface that a table model must implement and the usual superclass for table model implementations.
TableCellRenderer
DefaultTableCellRenderer
Respectively, the interface that a table cell renderer must implement and the usual implementation used.
TableCellEditor
DefaultCellEditor
AbstractCellEditor
Respectively, the interface that a table cell editor must implement, the usual implementation used, and the usual superclass for table cell editor implementations.
TableColumnModel
DefaultTableColumnModel
Respectively, the interface that a table column model must implement and the usual implementation used. You don't usually need to deal with the table column model directly unless you need to get the column selection model, or get a column index or object.
TableColumn Controls all the attributes of a table column, including resizability; minimum, preferred, current, and maximum widths; and an optional column-specific renderer/editor.
DefaultTableModel A Vector-based table model used by JTable when you construct a table specifying no data model and no data.
TableModelListener The interface that an object must implement to be notified of changes to the TableModel.
ListSelectionListener The interface that an object must implement to be notified of changes to the table's selection.

Creating and Setting Up a Table
Constructor or Method Purpose
JTable(TableModel)
JTable(TableModel, TableColumnModel)
JTable(TableModel, TableColumnModel, ListSelectionModel)
JTable()
JTable(int, int)
JTable(Object[][], Object[])
JTable(Vector, Vector)
Create a table. The optional TableModel argument specifies the model that provides the data to the table. The optional TableColumnModel and ListSelectionModel arguments let you specify the table column model and the row selection model. As an alternative to specifying a table model, you can supply data and column names, using arrays or vectors. Another option is to specify no data, optionally specifying the number of rows and columns (both integers) to be in the table.
void setPreferredScrollableViewportSize(Dimension) Set the size of the visible part of the table when it's viewed within a scroll pane.
JTableHeader getTableHeader() Get the component that displays the column names.

Manipulating Columns
Constructor or Method Purpose
TableColumnModel getColumnModel()
(in JTable)
Get the table's column model.
TableColumn getColumn(int)
Enumeration getColumns()
(in TableColumnModel)
Get one or all of the TableColumn objects for the table.
void setMinWidth(int)
void setPreferredWidth(int)
void setMaxWidth(int)
(in TableColumn)
Set the minimum, preferred, or maximum width of the column.
int getMinWidth()
int getPreferredWidth()
int getMaxWidth()
int getWidth()
(in TableColumn)
Get the minimum, preferred, maximum, or current width of the column.

Using Editors and Renderers
Method Purpose
void setDefaultRenderer(Class, TableCellRenderer)
void setDefaultEditor(Class, TableCellEditor)
(in JTable)
Set the renderer or editor used, by default, for all cells in all columns that return objects of the specified type.
void setCellRenderer(TableCellRenderer)
void setCellEditor(TableCellEditor)
(in TableColumn)
Set the renderer or editor used for all cells in this column.
TableCellRenderer getHeaderRenderer()
(in TableColumn)
Get the header renderer for this column.

Version Note:  As of 1.3, this method returns null if the column uses the default renderer. You generally use the TableHeader method getDefaultRenderer instead.

TableCellRenderer getDefaultRenderer()
(in JTableHeader)
Get the header renderer used when none is defined by a table column. Introduced in 1.3.

Implementing Selection
Method Purpose
void setSelectionMode(int) Set the selection intervals allowed in the table. Valid values are defined in ListSelectionModel (in the API reference documentation) as SINGLE_SELECTION, SINGLE_INTERVAL_SELECTION, and MULTIPLE_INTERVAL_SELECTION (the default).
void setSelectionModel(ListSelectionModel)
ListSelectionModel getSelectionModel()
Set or get the model used to control row selections.
void setRowSelectionAllowed(boolean)
void setColumnSelectionAllowed(boolean)
void setCellSelectionEnabled(boolean)
Set the table's selection orientation. The boolean argument specifies whether that particular type of selection is allowed. By default, row selection is allowed, and column and cell selection are not.

Examples that Use Tables

This table lists examples that use JTable and where those examples are described.

Example Where Described Notes
SimpleTableDemo Creating a Simple Table A basic table with no custom model. Does not include code to specify column widths or detect user editing.
SimpleTable-
SelectionDemo
Detecting User Selections Adds single selection and selection detection to SimpleTableDemo. By modifying the program's ALLOW_COLUMN_SELECTION and ALLOW_ROW_SELECTION constants, you can experiment with alternatives to the table default of allowing only rows to be selected.
TableDemo Creating a Table Model A basic table with a custom model.
TableFTFEditDemo Using an Editor to Validate User-Entered Text Modifies TableDemo to use a custom editor (a formatted text field variant) for all Integer data.
TableRenderDemo Using a Combo Box as an Editor Modifies TableDemo to use a custom editor (a combo box) for all data in the Sport column. Also intelligently picks column sizes. Uses renderers to display tool tips for the sport cells.
TableDialogEditDemo Using Other Editors Modifies TableDemo to have a cell renderer and editor that display a color and let you choose a new one, using a color chooser dialog.
TableToolTipsDemo Specifying Tool Tips for Cells, Specifying Tool Tips for Column Headers, Demonstrates how to use several techniques to set tool tip text for cells and column headers.
TableSorterDemo Sorting and Otherwise Manipulating Data Sorts column data by interposing a data manipulating table model between the data model and the table. Detects user clicks on column headers.
ListSelectionDemo How to Write a List Selection Listener Shows how to use all list selection modes, using a list selection listener that's shared between a table and list.
SharedModelDemo Nowhere Builds on ListSelectionDemo making the data model be shared between the table and list. If you edit an item in the first column of the table, the new value is reflected in the list.
TreeTable, TreeTable II Creating TreeTables in Swing, Creating TreeTables: Part 2 Examples that combine a tree and table to show detailed information about a hierarchy such as a file system. The tree is a renderer for the table.


Previous Page Lesson Contents Next Page Start of Tutorial > Start of Trail > Start of Lesson Search
Feedback Form

Copyright 1995-2004 Sun Microsystems, Inc. All rights reserved.

'java UI' 카테고리의 다른 글

File Connection Optiobal Package  (0) 2006.02.28
[펌] DataSource의 복제를 통한 다중 플레이어 생성방법  (0) 2005.12.02
jtable tutorial  (0) 2005.02.16
The Eclipse runtime options  (0) 2005.02.15
www.eclipse-plugins.info 의 순위  (0) 2005.02.12
BEYOND THE BASICS OF JOPTIONPANE  (0) 2005.02.11
Posted by 김용환 '김용환'

댓글을 달아 주세요

http://dev.eclipse.org/viewcvs/index.cgi/%7Echeckout%7E/org.eclipse.platform.doc.isv/reference/misc/runtime-options.html

 

The Eclipse runtime options

Last modified 14:45 Wednesday August 4, 2004

The Eclipse platform is highly configurable. Configuration input takes the form of command line arguments and System property settings. In many cases the command line arguments are simply short cuts for setting the related System properties. In fact, there are many more System property settings than command line arguments.

Command line arguments

Listed below are the command line arguments processed by various parts of the Eclipse runtime. Many of these values can also be specified using System properties either on the command line using -D VM arguments or by specifying there values in a config.ini file. Using this latter technique it is possible to customize your Eclipse without using command line arguments at all.

For each argument in the list, its corresponding System property key is given (in {}). Also given is the Eclipse runtime layer in which the command line argument is processed (in ()). This is useful for people replacing parts of the runtime to suit special needs.

-application <id> (Runtime)
equivalent to setting eclipse.application to <id>
-arch <architecture> (OSGi)
equivalent to setting osgi.arch to <architecture>
-clean (OSGi) NEW
equivalent to setting osgi.clean to "true"
-configuration <location> (Main)
equivalent to setting osgi.configuration.area to <location>
-console [port] (OSGi) NEW
equivalent to setting osgi.console to [port] or the empty string if the default port is to be used (i.e., when the port is not specified)
-consoleLog (Runtime)
equivalent to setting eclipse.consoleLog to "true"
-data <location> (OSGi)
equivalent to setting osgi.instance.area to <location>
-debug [options file] (OSGi)
equivalent to setting osgi.debug to [options file] or the empty string to simply enable debug (i.e., if the options file location is not specified)
-dev [entries] (OSGi)
equivalent to setting osgi.dev to [entries] or the empty string to simply enable dev mode (i.e., if entries are not specified)
-endSplash <command> (Main)
specifies the command to use to take down the splash screen. Typically supplied by the Eclipse executable.
-feature <feature id> (Runtime)
equivalent to setting eclipse.product to <feature id>
-framework <location> (Main) NEW
equivalent to setting osgi.framework to <location>
-initialize (Main)
initializes the configuration being run. All runtime related data structures and caches are refreshed. Any user/plug-in defined configuration data is not purged. No application is run, any product specifications are ignored and no UI is presented (e.g., the splash screen is not drawn)
-install <location> (Main)
equivalent to setting osgi.install.area to <location>
-keyring <location> (Runtime)
the location of the authorization database on disk. This argument has to be used together with the -password argument.
-nl <locale> (OSGi)
equivalent to setting osgi.nl to <locale>
-noLazyRegistryCacheLoading (Runtime)
equivalent to setting eclipse.noLazyRegistryCacheLoading to "true"
-noRegistryCache (Runtime)
equivalent to setting eclipse.noRegistryCache to "true"
-noSplash (Executable, Main)
controls whether or not the splash screen is shown
-os <operating system> (OSGi)
equivalent to setting osgi.os to <operating system>
-password <password> (Runtime)
the password for the authorization database
-pluginCustomization <location> (Runtime)
equivalent to setting eclipse.pluginCustomization to <location>
-product <id> (OSGi) NEW
equivalent to setting eclipse.product to <id>
-showSplash <command> (Main)
specifies the command to use to show the splash screen. Typically supplied by the Eclipse executable.
-user <location> (OSGi) NEW
equivalent to setting osgi.user.area to <location>
-vm <path to java executable> (Executable, Main) NEW
when passed to the Eclipse executable, this option is used to locate the Java VM to use to run Eclipse. It must be the full filesystem path to an appropriate Java executable. If not specified, the Eclipse executable uses a search algorithm to locate a suitable VM. In any event, the executable then passes the path to the actual VM used to Java Main using the -vm argument. Java Main then stores this value in eclipse.vm.
-vmargs [vmargs*] (Executable, Main) NEW
when passed to the Eclipse, this option is used to customize the operation of the Java VM to use to run Eclipse. If specified, this option must come at the end of the command line. Even if not specified on the executable command line, the executable will automatically add the relevant arguments (including the class being launched) to the command line passed into Java using the -vmargs argument. Java Main then stores this value in eclipse.vmargs.
-ws <window system> (OSGi)
equivalent to setting osgi.ws to <window system>

Obsolete command line arguments

The following command line arguments are no longer relevant or have been superceded and are consumed by the runtime and not passed on to the application being run to maintain backward compatibility. .

-boot
see -configuration
-classLoaderProperties
no longer relevant
-firstUse
no longer relevant
-newUpdates
no longer relevant
-noPackagePrefixes
no longer relevant
-noUpdate
no longer relevant
-plugins
no longer relevant
-update
no longer relevant

Others

The following command line arguments are defined by various Eclipse plug-ins and are only supported if the defining plug-in is installed, resolved and activated.

-noVersionCheck (workbench)
<description>
-perspective (workbench)
<description>
-refresh (org.eclipse.core.resources)
<description>
-showLocation (org.eclipse.ui.ide.workbench)
<description>
-allowDeadlock
<description>

System properties

The following System properties are used by the Eclipse runtime. Note that those starting with "osgi" are specific to the OSGi framework implementation while those starting with "eclipse" are particular to the Eclipse runtime layered on top of the OSGi framework.

Many of these properties have command line equivalents (see the command line arguments section and the value in braces {}). Users are free to use either command line or property settings to specify a value. Properties can be set in the following ways:

  • use -DpropName=propValue as a VM argument to the Java VM
  • set the desired property in the config.ini file in the appropriate configuration area
eclipse.application {-application}
the identifier of the application to run. The value given here overrides any application defined by the product (see eclipse.product) being run
eclipse.commands
sdf
eclipse.consoleLog
if "true", any log output is also sent to Java's System.out (typically back to the command shell if any). Handy when combined with -debug
eclipse.debug.startupTime
the time in milliseconds when the Java VM for this session was started
eclipse.exitcode
<description>
eclipse.exitdata
<description>
eclipse.manifestConverter
the class name of the manifest converter class to use when converting legacy plugin.xml files to manifest.mf files
eclipse.noExtensionMunging
if "true", legacy registry extension are left as-is. By default such extensions are updated to use the new extension point ids found in Eclipse 3.0.
eclipse.noLazyRegistryCacheLoading {-noLazyRegistryCacheLoading}
if "true", the platform's plug-in registry cache loading optimization is deactivated. By default, configuration elements are loaded from the registry cache (when available) only on demand, reducing memory footprint. This option forces the registry cache to be fully loaded at startup.
eclipse.noRegistryCache {-noRegistryCache}
if "true", the internal extension registry cache is neither read or written
eclipse.pluginCustomization {-pluginCustomization}
the file system location of a properties file containing default settings for plug-in preferences. These default settings override default settings specified in the primary feature. Relative paths are interpreted relative to the current working directory for eclipse itself.
eclipse.product {-product}
the identifier of the product being run. This controls various branding information and what application is used.
eclipse.vm {-vm}
the path to the Java executable used to run Eclipse. This information is used to construct relaunch command lines.
eclipse.vmargs {-vmargs}
lists the VM arguments used to run Eclipse. This information is used to construct relaunch command lines.
osgi.adaptor
the class name of the OSGi framework adaptor to use.
osgi.arch {-arch}
see -arch
osgi.baseConfiguration.area
asf
osgi.bundles
The comma-separated list of bundles which are automatically installed and optionally started once the system is up and running. Each entry is of the form:
    <URL | simple bundle location>[@ [<start-level>] [":start"]]
If the start-level (>0 integer) is omitted then the framework will use the default start level for the bundle. If the "start" tag is added then the bundle will be marked as started after being installed. Simple bundle locations are interepreted as relative to the framework's parent directory. The start-level indicates the OSGi start level at which the bundle should run. If this value is not set, the system computes an appropriate default.
osgi.clean
if set to "true", any cached data used by the OSGi framework and eclipse runtime will be wiped clean. This will clean the caches used to store bundle dependency resolution and eclipse extension registry data. Using this option will force eclipse to reinitialize these caches.
osgi.configuration.cascaded
if set to "true", this configuration is cascaded to a parent configuration. See the section on locations for more details.
osgi.configuration.area {-configuration}
the configuration location for this run of the platform. The configuration determines what plug-ins will run as well as various other system settings. See the section on locations for more details.
osgi.configuration.area.default
the default configuration location for this run of the platform. The configuration determines what plug-ins will run as well as various other system settings. This value (i.e., the default setting) is only used if no value for the osgi.configuration.area is set. See the section on locations for more details.
osgi.console {-console}
if set to a non-null value, the OSGi console (if installed) is enabled. If the value is a suitable integer, it is interpreted as the port on which the console listens and directs its output to the given port. Handy for investigating the state of the system.
osgi.console.class
the class name of the console to run if requested
osgi.debug {-debug}
if set to a non-null value, the platform is put in debug mode. If the value is a string it is interpreted as the location of the .options file. This file indicates what debug points are available for a plug-in and whether or not they are enabled. If a location is not specified, the platform searches for the .options file under the install directory.
osgi.dev {-dev}
if set to the empty string, dev mode is simply turned on. This property may also be set to a comma-separated class path entries which are added to the class path of each plug-in or a URL to a Java properties file containing custom classpath additions for a set of plug-ins. For each plug-in requiring a customized dev time classpath the file will contain an entry of the form
    <plug-in id>=<comma separated list of classpath entries to add>
where plug-in id "*" matches any plug-in not otherwise mentioned.
osgi.framework
the URL location of the OSGi framework. Useful if the Eclipse install is disjoint. See the section on locations for more details.
osgi.frameworkClassPath
a comma separated list of classpath entries for the OSGi framework implementation. Relative locations are interpreted as relateve to the framework location (see osgi.framework)
osgi.install.area {-install}
the install location of the platform. This setting indicates the location of the basic Eclipse plug-ins and is useful if the Eclipse install is disjoint. See the section on locations for more details.
osgi.instance.area {-data}
the instance data location for this session. Plug-ins use this location to store their data. For example, the Resources plug-in uses this as the default location for projects (aka the workspace). See the section on locations for more details.
osgi.instance.area.default
the default instance data location for this session. Plug-ins use this location to store their data. For example, the Resources plug-in uses this as the default location for projects (aka the workspace). This value (i.e., the default setting) is only used if no value for the osgi.instance.area is set. See the section on locations for more details.
osgi.manifest.cache
the location where generated manifests are discovered and generated. The default is in the configuration area but the manifest cache can be stored separately.
osgi.nl {-nl}
the name of the locale on which Eclipse platform will run. NL values should follow the standard Java locale naming conventions.
osgi.os {-os}
the operating system value. The value should be one of the Eclipse processor architecture names known to Eclipse (e.g., x86, sparc, ...).
osgi.splashLocation
the absolute URL location of the splash screen (.bmp file) to to show while starting Eclipse. This property overrides any value set in osgi.splashPath.
osgi.splashPath
a comma separated list of URLs to search for a file called splash.bmp. This property is overriden by any value set in osgi.splashLocation.
osgi.user.area {-user}
the location of the user area. The user area contains data (e.g., preferences) specific to the OS user and independent of any Eclipse install, configuration or instance. See the section on locations for more details.
osgi.user.area.default
the default location of the user area. The user area contains data (e.g., preferences) specific to the OS user and independent of any Eclipse install, configuration or instance. This value (i.e., the default setting) is only used if no value for the osgi.user.area is set. See the section on locations for more details.
osgi.ws {-ws}
the window system value. The value should be one of the Eclipse window system names known to Eclipse (e.g., win32, motif, ...).
osgi.syspath
<xxx still used? fix the name>

Locations

The Eclipse runtime defines a number of locations which give plug-in developers context for reading/storing data and Eclipse users a control over the scope of data sharing and visibility. Eclipse defines the following notions of location:

User (-user) {osgi.user.area} [@none, @noDefault, @user.home, @user.dir, filepath, url]
User locations are specific to, go figure, users. Typically the user location is based on the value of the Java user.home system property but this can be overridden. Information such as user scoped preferences and login information may be found in the user location.
Install (-install) {osgi.install.area} [@user.home, @user.dir, filepath, url]
An install location is where Eclipse itself is installed. In practice this location is the directory (typically "eclipse") which is the parent of the startup.jar or eclipse.exe being run. This location should be considered read-only to normal users as an install may be shared by many users. It is possible to set the install location and decouple startup.jar from the rest of Eclipse.
Configuration (-configuration) {osgi.configuration.area} [@none, @noDefault, @user.home, @user.dir, filepath, url]
Configuration locations contain files which identify and manage the (sub)set of an install to run. As such, there may be many configurations per install. Installs may come with a default configuration area but typical startup scenarios involve the runtime attempting to find a more writable configuration location.
Instance (-data) {osgi.instance.area} [@none, @noDefault, @user.home, @user.dir, filepath, url]
Instance locations contain user-defined data artifacts. For example, the Resources plug-in uses the instance area as the workspace location and thus the default home for projects. Other plugins are free to write whatever files they like in this location.

While users can set any of these locations, Eclipse will compute reasonable defaults if values are not given. The most common usecase for setting location is the instance area or, in the IDE context, the workspace. To run the default Eclipse configuration on a specific data set you can specify:

    eclipse -data c:\mydata

More detail

Locations are URLs. For simplicity, file paths are also accepted and automatically converted to file: URLs. For better control and convenience, there are also a number of predefined symbolic locations which can be used. Note that not all combinations of location type and symbolic value are valid. A table below details which combinations are possible. Since the default case is for all locations to be set, valid and writable, some plug-ins may fail in other setups even if they are listed as possible. For example, it is unreasonable to expect a plugin focused on user data (e.g., the Eclipse Resources plug-in) to do much if the instance area is not defined. It is up to plug-in developers to choose the setups they support and design their function accordingly.

@none
Indicates that the corresponding location should never be set either explicitly or to its default value. For example, an RCP style application which has no user data may use osgi.instance.area=@none to prevent extraneous files being written to disk. @none must not be followed by any additional path segments.
@noDefault
Forces a location to be undefined or explicitly defined (i.e., Eclipse will not automatically compute a default value). This is useful where you want to allow for data in the corresponding location but the Eclipse default value is not appropriate. @noDefault must not be followed by any additional path segments.
@user.home
Directs Eclipse to compute a location value relative to the user's home directory. @user.home can be followed by additional path segments. In all cases, the string "@user.home" is simply replaced with the value of the Java "user.home" System property. For example, setting
    osgi.instance.area=@user.home/myWorkspace
results in a value of
    file:/users/bob/myWorkspace
@user.dir
Directs Eclipse to compute a location value relative to the current working directory. @user.dir can be followed by additional path segments. In all cases, the string "@user.dir" is simply replaced with the value of the Java "user.dir" System property. For example, setting
    osgi.instance.area=@user.dir/myWorkspace
results in a value of
    file:/usr/share/eclipse/myWorkspace
location/value
supports default
file/URL
@none
@noDefault
@user.home
@user.dir
instance
yes
yes
yes
yes
yes
yes (default)
configuration
yes
yes
yes*
yes*
yes
yes
install
no
yes
no
no
yes
yes
user
yes
yes
yes
yes
yes
yes

* indicates that this setup is technically possible but pragmatically quite difficult to manage. In particular, without a configuration location the Eclipse runtime may only get as far as starting the OSGi framework.

Legal notices.

'java UI' 카테고리의 다른 글

File Connection Optiobal Package  (0) 2006.02.28
[펌] DataSource의 복제를 통한 다중 플레이어 생성방법  (0) 2005.12.02
jtable tutorial  (0) 2005.02.16
The Eclipse runtime options  (0) 2005.02.15
www.eclipse-plugins.info 의 순위  (0) 2005.02.12
BEYOND THE BASICS OF JOPTIONPANE  (0) 2005.02.11
Posted by 김용환 '김용환'

댓글을 달아 주세요

www.eclipse-plugins.info

Top rated


pages: 1 2 3 Next>
    Plugin   avg. rating   # ratings
1 Hibernate Synchronizer 8.8 48
2 VSS Plugin for Eclipse 8.7 55
3 XMLBuddy 8.5 89
4 SWT/Swing Designer 8.5 43
5 JLint 8.5 4
6 Persistence for Eclipse 8.5 4
7 JasperAssistant 8.5 22
8 SQLExplorer 8.5 18
9 Sysdeo Eclipse Tomcat Launcher 8.4 64
10 JadClipse 8.4 13
11 EclipseColorer 8.4 11
12 Jalopy 8.4 13
13 EclipseProfiler 8.4 25
14 QuantumDB 8.4 18
15 ColorEditor 8.4 7
16 EditorList 8.4 5
17 Call Hierarchy View 8.4 11
18 Implementors 8.4 12
19 Checkclipse 8.4 11
20 W4T Eclipse 8.4 9
21 RMI Plugin for Eclipse 8.4 5
22 Regular Expression Tester 8.4 23
23 Exadel Struts Studio 8.4 16
24 DBEdit 8.4 16
25 PriDE Entity Generator 8.4 5
26 Jigloo SWT/Swing GUI Builder 8.4 16
27 Log4E 8.4 14
28 AnyEdit tools 8.3 6
29 eclipsetidy 8.3 3
30 EMF (Eclipse Modeling Framework) 8.3 6
31 MyEclipse Enterprise Workbench 8.3 49
32 EPIC - Eclipse Perl Integration 8.3 10
33 Oxygen - XML editor 8.3 6
34 SDE for Eclipse 8.3 3
35 NitroX 8.3 6
36 Eclipse-games 8.2 4
37 ToString generator 8.2 4
38 Eiffel for Eclipse (EfE) 8.2 5
39 PMD For Eclipse 8.1 7
40 Metrics 8.1 9
pages: 1 2 3 Next>
note: plugins need to have received at least three ratings to be listed.
 
 

'java UI' 카테고리의 다른 글

File Connection Optiobal Package  (0) 2006.02.28
[펌] DataSource의 복제를 통한 다중 플레이어 생성방법  (0) 2005.12.02
jtable tutorial  (0) 2005.02.16
The Eclipse runtime options  (0) 2005.02.15
www.eclipse-plugins.info 의 순위  (0) 2005.02.12
BEYOND THE BASICS OF JOPTIONPANE  (0) 2005.02.11
Posted by 김용환 '김용환'

댓글을 달아 주세요

.
.
Core Java
Technologies Technical Tips
.
   View this issue as simple text January 22, 2004    

In this Issue

Welcome to the Core Java Technologies Tech Tips for January 22, 2004. Here you'll get tips on using core Java technologies and APIs, such as those in Java 2 Platform, Standard Edition (J2SE).

This issue covers:

-Beyond the Basics of JOptionPane
-Monitoring Class Loading and Garbage Collection

These tips were developed using Java 2 SDK, Standard Edition, v 1.4.2.

This issue of the Core Java Technologies Tech Tips is written by John Zukowski, president of JZ Ventures, Inc.

See the Subscribe/Unsubscribe note at the end of this newsletter to subscribe to Tech Tips that focus on technologies and products in other Java platforms.

.
.

BEYOND THE BASICS OF JOPTIONPANE

The Swing component set in J2SE includes a special class for creating a panel to be placed in a popup window. You can use this panel to display a message to the user and to get a response from the user. The panel presents content in four areas, one each for an icon, message, input, and buttons. You don't need to use any of the areas, although you would typically present at least a message and a button.

The icon area is for the display of a javax.swing.Icon. The icon is meant to indicate the type of message being displayed. There are default icons provided by the specific look and feel you use. The default images for these icons are specified through a property setting to the look and feel. The property setting points to the appropriate resource for each message type:

  • OptionPane.informationIcon
  • OptionPane.warningIcon
  • OptionPane.errorIcon
  • OptionPane.questionIcon

You don't have to change the default properties, though you could with a call to UIManager.put(property name, new resource). With the defaults in place, you simply identify the appropriate message type with a constant of JOptionPane:

  • JOptionPane.PLAIN_MESSAGE
  • JOptionPane.INFORMATION_MESSAGE
  • JOptionPane.WARNING_MESSAGE
  • JOptionPane.ERROR_MESSAGE
  • JOptionPane.QUESTION_MESSAGE

The plain variety maps to no icon, while the others use a default icon from the look and feel.

The second area of the JOptionPane is the message area. This is typically used to display a text message. However, you could show any number of objects here. The message type determines how a message is displayed.

The input area is next. Here is where you can get a response to a message from the user. To prompt for a response you can use a free form text field, a combo box, or even a list control. For Yes/No type prompts, you would instead use the button area, described next.

Last is the button area, another response-like area. When a user selects a button it signals the end of usage for the JOptionPane. Default sets of button labels are available. (As is the case for icons, these too come from property settings, such as OptionPane.yesButtonText.) You can also provide your own button labels. You can display any number of buttons (including no buttons) with any set of labels. The predefined button label is localized for several languages: English (en), German (de), Spanish (es), French (fr), Italian (it), Japanese (ja), Korean (ko), Swedish (sv), and two varieties of Chinese (zh_CN / zh_TW). If you provide your own labels, you need to localize them yourself.

The predefined sets of buttons are defined by a set of JOptionPane constants:

  • DEFAULT_OPTION
  • YES_NO_OPTION
  • YES_NO_CANCEL_OPTION
  • OK_CANCEL_OPTION

Default maps to a single OK button.

Using JOptionPane

The JOptionPane class contains seven constructors, each returns a component that you can place anywhere. However, more typically you would use a factory method that creates the component and automatically places it inside a JDialog or JInternalFrame. There are eight of these factory methods (two varieties of four methods) that JOptionPane provides:

  • show[Internal]MessageDialog
  • show[Internal]ConfirmDialog
  • show[Internal]InputDialog
  • show[Internal]OptionDialog

The Internal variety creates a JOptionPane and shows it in a JInternalFrame. The other variety creates a JOptionPane and shows it in a JDialog. This tip only discusses the dialog variety.

The message dialog is meant to show a message that the user confirms by selecting the button (or closing the dialog). The message dialog is not meant to return a value.

In its simplest case, you would use code like the following to show a message dialog:

   JOptionPane.showMessageDialog(
      component, "Hello, World");

The system centers the dialog over the component argument.

There are two other variations for showing a message dialog. These allow you to customize the window title, customize the message type (to use the default icon), and set a customized icon:

  • showMessageDialog(Component parentComponent,
    Object message,
    String title,
    int messageType)
  • showMessageDialog(Component parentComponent,
    Object message,
    String title,
    int messageType,
    Icon icon)

The method for showing a confirm dialog has four variations:

  • showConfirmDialog(Component parentComponent,
    Object message)
  • showConfirmDialog(Component parentComponent,
    Object message,
    String title,
    int optionType)
  • showConfirmDialog(Component parentComponent,
    Object message,
    String title,
    int optionType,
    int messageType)
  • showConfirmDialog(Component parentComponent,
    Object message,
    String title,
    int optionType,
    int messageType,
    Icon icon)

The simplest variation brings up a dialog with a question icon. The dialog displays Select an Option as the title, has Yes, No, and Cancel as button labels.

   JOptionPane.showConfirmDialog(component, "Lunch?");

If you don't like the defaults, you can change them by using one of the other methods. You'll find that everything is changeable with JOptionPane.

Unlike the message dialog, the confirm dialog does require a return value. Here, you really do want to know which button the user selected. The confirm dialog returns an integer, indicated by one of the following constants of the JOptionPane class:

  • CANCEL_OPTION
  • CLOSED_OPTION (used when the used closed popup window)
  • NO_OPTION
  • OK_OPTION
  • YES_OPTION

Passing in a setting of OK_CANCEL_OPTION for the option type changes the buttons shown in the confirm dialog to OK and Cancel. Comparing the value returned to the constant, indicates which button the user selected.

Checking for the return value changes the one line above to quite a few more:

   int returnValue = JOptionPane.showConfirmDialog(
     component, "Lunch?");
   String message = null;
   if (returnValue == JOptionPane.YES_OPTION) {
     message = "Yes";
   } else if (returnValue == JOptionPane.NO_OPTION) {
     message = "No";
   } else if (returnValue == JOptionPane.CANCEL_OPTION) {
     message = "Cancel";
   } else if (returnValue == JOptionPane.CLOSED_OPTION) {
     message = "Closed";
   }
   System.out.println("User selected: " + message);

The input dialog method has six variations. Five return a String:

  • showInputDialog(Object message)
  • showInputDialog(Object message,
    Object initialSelectionValue)
  • showInputDialog(Component parentComponent,
    Object message)
  • showInputDialog(Component parentComponent,
    Object message,
    Object initialSelectionValue)
  • showInputDialog(Component parentComponent,
    Object message,
    String title,
    int messageType)

One of the variations returns an Object:

  • showInputDialog(Component parentComponent,
    Object message,
    String title,
    int messageType,
    Icon icon,
    Object[] selectionValues,
    Object initialSelectionValue)

The simplest variation shows the message in a question dialog. The dialog displays Input as the frame title, and has OK and Cancel buttons. Because there is no component provided, the frame is centered over the whole screen.

   String value = JOptionPane.showInputDialog("Name");

As is the case for other types, when you show the input dialog, you can set the parent component, frame title, message type, or icon. However the buttons are fixed at OK and Cancel. You can also set the initial value in the text field.

The last method variation for the input dialog is special. Instead of offering the user a text field to enter selections, you provide an array of objects (typically strings) from which to choose. Depending on how many values you provide, the look and feel will present either a JComboBox or JList for the user selections. Here's an example that uses this variation. Here an input dialog prompts a user to select a day of the week. The default is the last day of the week. The example uses a smallList for the days of the week.

   String smallList[] = {
     "Sunday",
     "Monday",
     "Tuesday",
     "Wednesday",
     "Thursday",
     "Friday",
     "Saturday"
   };
   String value = 
     (String)JOptionPane.showInputDialog(
       component, 
       "Which Day?", 
       "Day", 
       JOptionPane.QUESTION_MESSAGE, 
       null, // Use default icon
       smallList, 
       smallList[smallList.length-1]);
   System.out.println("Day: " + value);

For a larger list, the code looks essentially the same. Here the list of system properties are used as the choices.

   Object largeList[] = 
     System.getProperties().keySet().toArray();
   String value = 
     (String)JOptionPane.showInputDialog(
       component, 
       "Which Property?", 
       "Property", 
      JOptionPane.QUESTION_MESSAGE, 
       null, 
       largeList, 
       largeList[largeList.length-1]);


   System.out.println("Property: " + value);

The final dialog type is an all encompassing one, showOptionDialog. There is only one version of the method. Here, you can set everything:

  • showOptionDialog(Component parentComponent,
    Object message,
    String title,
    int optionType,
    int messageType,
    Icon icon,
    Object[] options,
    Object initialValue)

The only thing new here is the options array. This is how you can customize the set of available buttons. Notice that this is an Object array, not a String array. If the Object is a Component, that component is used in the dialog. This allows you to place icons in the buttons, for instance. More typically, you would provide an array of strings, and their labels would be used as the button labels. The initialValue is then used to select which of the options gets the default selection.

The showOptionDialog method returns an int. This indicates the position selected from the options array. CLOSED_OPTION is still returned if the user closed the dialog.

   String options[] = {"Yes", "Not Now", "Go Away"};
   int value = JOptionPane.showOptionDialog(
       component,
       "Lunch?",
       "Lunch Time",
       JOptionPane.YES_NO_OPTION, // Need something  
         JOptionPane.QUESTION_MESSAGE,
       null, // Use default icon for message type
       options,
       options[1]);
   if (value == JOptionPane.CLOSED_OPTION) {
     System.out.println("Closed window");
   } else {
     System.out.println("Selected: " + options[value]);
   }

If you don't want buttons, pass in an empty array for the options.

Adding Word Wrap

The JOptionPane component has a read-only property (MaxCharactersPerLineCount) for the maximum number of characters per line. By default, this is Integer.MAX_VALUE. By subclassing JOptionPane, you can override this setting. Changing this setting allows the component to word-wrap when a message is really long.

   public static JOptionPane getNarrowOptionPane(
                       int maxCharactersPerLineCount) {
     // Our inner class definition
     class NarrowOptionPane extends JOptionPane {
       int maxCharactersPerLineCount;
       NarrowOptionPane(int maxCharactersPerLineCount) {
         this.maxCharactersPerLineCount = 
           maxCharactersPerLineCount;
       }
       public int getMaxCharactersPerLineCount() {
         return maxCharactersPerLineCount;
       }
     }


     return new NarrowOptionPane(
       maxCharactersPerLineCount);
   }

By subclassing, you can no longer use the static helper methods such as showMessageDialog. Here's how you manually create and show the component:

   String msg = "This is a really long message. ...";
   JOptionPane pane = getNarrowOptionPane(50);
   pane.setMessage(msg);
   pane.setMessageType(JOptionPane.INFORMATION_MESSAGE);
   JDialog dialog = pane.createDialog(
     component, "Width 50");
   dialog.show();

Of course, you can add a "\n" to the message, but then you have to count the characters per line.

Message as Object

At this point you might ask why the message argument to all the showXXXDialog methods is an Object. The answer is that it's because the message argument to all these methods doesn't have to be a String. You can pass in any Object. Each object is "added" to the message area, one on top of the other. For instance, if you pass in an array of two strings, it creates a message on two lines:

   String msg[] = {"Welcome", "Home"};
   JOptionPane.showMessageDialog(component, msg);

The objects you add can be components, icons, or objects. Components are added as such. Icons are shown in a label, as are strings. For other objects, their string representation (toString()) is shown. For instance, the following component can be added to an option pane. As the user changes the selection in the slider, the option pane's value is updated:

   public static JSlider getSlider(
                        final JOptionPane optionPane) {
     JSlider slider = new JSlider();
     slider.setMajorTickSpacing (10);
     slider.setPaintTicks(true);
     slider.setPaintLabels(true);
     ChangeListener changeListener = 
       new ChangeListener() {
       public void stateChanged(
                   ChangeEvent changeEvent) {
         JSlider theSlider = 
             (JSlider)changeEvent.getSource();
         if (!theSlider.getValueIsAdjusting()) {
           optionPane.setInputValue(
             new Integer(theSlider.getValue()));
         }
       }
     };
     slider.addChangeListener(changeListener);
     return slider;
   }

Because you have to pass the option pane to the method, here again, you can't use one of the shortcuts to create the dialog:

   JOptionPane optionPane = new JOptionPane();
   JSlider slider = getSlider(optionPane);
   Object msg[] = {"Select a value:", slider};
   optionPane.setMessage(msg);
   optionPane.setMessageType(
     JOptionPane.QUESTION_MESSAGE);
   optionPane.setOptionType(
     JOptionPane.OK_CANCEL_OPTION);
   JDialog dialog = optionPane.createDialog(
       Options.this, "Select Value");
   dialog.show();
   Object value = optionPane.getValue();
   if (value == null || !(value instanceof Integer)) {
     System.out.println("Closed");
   } else {
     int i = ((Integer)value).intValue();
     if (i == JOptionPane.CLOSED_OPTION) {
       System.out.println("Closed");
     } else if (i == JOptionPane.OK_OPTION) {
       System.out.println("OKAY - value is: " +
                  optionPane.getInputValue());
     } else if (i == JOptionPane.CANCEL_OPTION) {
       System.out.println("Cancelled");
     }
   }

Notice that as you start getting fancier with JOptionPane, you lose the ability to use the shortcut methods. And, you have to do special handling of the return value. You first need to use getValue for the JOptionPane to determine which button the user selected. Then, for when the user presses the OK button, you need to use the getInputValue method to get the value from the underlying slider.

Sounds

Swing provides for auditory cues related to the four types of icons:

  • OptionPane.errorSound
  • OptionPane.informationSound
  • OptionPane.questionSound
  • OptionPane.warningSound

By setting these properties, you can get sounds when your option panes are displayed. You can set the individual sounds with lines like the following:

   UIManager.put("OptionPane.questionSound", 
     "sounds/OptionPaneError.wav");

Or set all of them with the system defaults as follows:

   UIManager.put("AuditoryCues.playList",
     UIManager.get("AuditoryCues.defaultCueList"));

Audio cues are disabled by default because they might have problems on some platforms. It is recommended that you use them with care until the issues have been resolved.

Complete Example

Here is the source code for a complete example that uses the features explored in this tip.

   import javax.swing.*;
   import javax.swing.event.*;
   import java.awt.*;
   import java.awt.event.*;
   import java.util.Locale;

   public class Options extends JFrame {
     private static class FrameShower
         implements Runnable {
       final Frame frame;
       public FrameShower(Frame frame) {
         this.frame = frame;
       }
       public void run() {
         frame.show();
       }
     }

     public static JOptionPane getNarrowOptionPane(
         int maxCharactersPerLineCount) {
       // Our inner class definition
       class NarrowOptionPane extends JOptionPane {
         int maxCharactersPerLineCount;
         NarrowOptionPane(
                   int maxCharactersPerLineCount) {
           this.maxCharactersPerLineCount = 
              maxCharactersPerLineCount;
     }
         public int getMaxCharactersPerLineCount() {
           return maxCharactersPerLineCount;
         }
       }

    return new NarrowOptionPane(
               maxCharactersPerLineCount);
  }

     public static JSlider getSlider(
                        final JOptionPane optionPane) {
       JSlider slider = new JSlider();
       slider.setMajorTickSpacing (10);
       slider.setPaintTicks(true);
       slider.setPaintLabels(true);
       ChangeListener changeListener = 
                            new ChangeListener() {
         public void stateChanged(
                           ChangeEvent changeEvent) {
           JSlider theSlider = (
             JSlider)changeEvent.getSource();
           if (!theSlider.getValueIsAdjusting()) {
             optionPane.setInputValue(new Integer(  
               theSlider.getValue()));
           }
         }
       };
       slider.addChangeListener(changeListener);
       return slider;
     }

     public Options() {
       super("JOptionPane Usage");
       setDefaultCloseOperation(EXIT_ON_CLOSE);
       Container contentPane = getContentPane();
       contentPane.setLayout(new FlowLayout());
       JButton message = new JButton("Message");
       ActionListener messageListener = 
                               new ActionListener() {
         public void actionPerformed(ActionEvent e) {
           JOptionPane.showMessageDialog(
             Options.this, "Hello, World");
         }
       };
       message.addActionListener(messageListener);
       contentPane.add(message);
       JButton confirm = new JButton("Confirm");  
       ActionListener confirmListener = 
        new ActionListener() {
         public void actionPerformed(ActionEvent e) {
           int returnValue = 
             JOptionPane.showConfirmDialog(
           Options.this, "Lunch?");
           String message = null;           
           if (returnValue == JOptionPane.YES_OPTION) {
             message = "Yes";
           } else if (
               returnValue == JOptionPane.NO_OPTION) {
             message = "No";
           } else if (
               returnValue == JOptionPane.CANCEL_OPTION) {
             message = "Cancel";
           } else if (
               returnValue == JOptionPane.CLOSED_OPTION) {
             message = "Closed";
           }
           System.out.println("User selected: " + message);
         }
       };
       confirm.addActionListener(confirmListener);
       contentPane.add(confirm);
       JButton inputText = new JButton("Input Text");
       ActionListener inputTextListener = 
                               new ActionListener() {
         public void actionPerformed(ActionEvent e) {
           String value = 
             JOptionPane.showInputDialog("Name");
           System.out.println("Name: " + value);
         }
       };
       inputText.addActionListener(inputTextListener);
       contentPane.add(inputText);
       JButton inputCombo = new JButton("Input Combo");
       ActionListener inputComboListener = 
                                 new ActionListener() {
         public void actionPerformed(ActionEvent e) {
           String smallList[] = {
             "Sunday",
             "Monday",
             "Tuesday",
             "Wednesday",
             "Thursday",
             "Friday",
             "Saturday"
           };
           String value = 
             (String)JOptionPane.showInputDialog(
             Options.this, "Which Day?", "Day", 
             JOptionPane.QUESTION_MESSAGE, null, 
             smallList, smallList[smallList.length-1]);
           System.out.println("Day: " + value);
         }
       };
       inputCombo.addActionListener(inputComboListener);
       contentPane.add(inputCombo);
       JButton inputList = new JButton("Input List");     
       ActionListener inputListListener = 
                              new ActionListener() {
        public void actionPerformed(ActionEvent e) {
           Object largeList[] = 
             System.getProperties().keySet().toArray();
           String value = 
             (String)JOptionPane.showInputDialog(
             Options.this, "Which Property?", "Property", 
             JOptionPane.QUESTION_MESSAGE, null, 
             largeList, largeList[largeList.length-1]);
             System.out.println("Property: " + value);
         }
       };              
       inputList.addActionListener(inputListListener);
       contentPane.add(inputList);
       JButton all = new JButton("All");
       ActionListener allListener = 
                               new ActionListener() {
         public void actionPerformed(ActionEvent e) {
           String options[] = 
             {"Yes", "Not Now", "Go Away"};
           int value = JOptionPane.showOptionDialog(
               Options.this,
               "Lunch?",
               "Lunch Time",
               JOptionPane.YES_NO_OPTION, 
               // Message type
               JOptionPane.QUESTION_MESSAGE,
               null, // Use default icon for message type
               options,
               options[1]);
           if (value == JOptionPane.CLOSED_OPTION) {
             System.out.println("Closed window");
           } else {
             System.out.println(
               "Selected: " + options[value]);
           }
         }
       };       
       all.addActionListener(allListener);
       contentPane.add(all);
       JButton wide = new JButton("Wide");
       ActionListener wideListener = 
                               new ActionListener() {
         public void actionPerformed(ActionEvent e) {
           String msg = 
             "This is a really long message. " + 
             "This is a really long message. " + 
             "This is a really long message. " + 
             "This is a really long message. " + 
             "This is a really long message. " +
             "This is a really long message.";
           JOptionPane pane = getNarrowOptionPane(50);
           pane.setMessage(msg);
           pane.setMessageType(
             JOptionPane.INFORMATION_MESSAGE);
           JDialog dialog = 
              pane.createDialog(Options.this, "Width 50");
           dialog.show();
         }
       };       
       wide.addActionListener(wideListener);
       contentPane.add(wide);
       JButton twoLine = new JButton("Two Line");
       ActionListener twoLineListener = 
                               new ActionListener() {
         public void actionPerformed(ActionEvent e) {
           String msg[] = {"Welcome", "Home"};
           JOptionPane.showMessageDialog(
             Options.this, msg);
         }
       };       
       twoLine.addActionListener(twoLineListener);
       contentPane.add(twoLine);
       JButton slider = new JButton("Slider");
       ActionListener sliderListener = 
                               new ActionListener() {
         public void actionPerformed(ActionEvent e) {
           JOptionPane optionPane = new JOptionPane();
           JSlider slider = getSlider(optionPane);
           Object msg[] = {"Select a value:", slider};
           optionPane.setMessage(msg);
           optionPane.setMessageType(
             JOptionPane.QUESTION_MESSAGE);
           optionPane.setOptionType(
             JOptionPane.OK_CANCEL_OPTION);
             JDialog dialog = optionPane.createDialog(
                Options.this, "Select Value");
           dialog.show();
           Object value = optionPane.getValue();
           if (value == null || !(value instanceof Integer)) {
             System.out.println("Closed");
           } else {
             int i = ((Integer)value).intValue();
             if (i == JOptionPane.CLOSED_OPTION) {
               System.out.println("Closed");
             } else if (i == JOptionPane.OK_OPTION) {
               System.out.println("OKAY - value is: " +
                          optionPane.getInputValue());
             } else if (i == JOptionPane.CANCEL_OPTION) {
               System.out.println("Cancelled");
             }
           }
         }
       };
       slider.addActionListener(sliderListener);
       contentPane.add(slider);
       setSize(300, 200);
     }
     
     public static void main(String args[]) {
       UIManager.put("AuditoryCues.playList",
         UIManager.get("AuditoryCues.defaultCueList"));
       JFrame frame = new Options();
       Runnable runner = new FrameShower(frame);
       EventQueue.invokeLater(runner);
     }
   }

For additional information about JOptionPane, see the How to Make Dialogs trail in The Java Tutorial and the javadoc for the JOptionPane class.

.
.

MONITORING CLASS LOADING AND GARBAGE COLLECTION

Have you ever wondered what classes are loaded when you launch an application or from where the classes are loaded? Have you ever wondered when garbage collection runs or how long it takes? The java command line tool offers several different command line options that you can use to get answers to those questions.

You might already be familiar with a number of command line options available with the java command line tool, such as -cp, -Xms, and -Xmx. The -cp option is used for specifying the classpath. The -Xms and -Xmx options are used to specify the heap size. For example, instead of setting the CLASSPATH environment variable, you can use the -cp option to tell the system to look in a specific directory for necessary class files:

   java -cp ExampleDir MyExample

Here, the system will look in the ExampleDir subdirectory for the MyExample.class file and anything else needed besides the system classes. The ExampleDir in the command line tells the system to look only in the ExampleDir directory (assume that it's the parent directory). If MyExample.class is located in the current working directory, the system would not find it.

Two less frequently used command line features report on class loading and garbage collection. The -verbose:class option reports when a class is loaded into the Java virtual machine and from where it came. For instance, if you use the -verbose:class option when loading the SwingSet2 demo that comes with the J2SE 1.4.2 SDK, you get a report on the many different classes that are loaded as part of the demo, such the following two:

   java -verbose:class -jar
       C:\j2sdk1.4.2\demo\jfc\SwingSet2\SwingSet2.jar

   [Loaded FilePreviewer]
   [Loaded javax.swing.plaf.TableUI from 
     C:\j2sdk1.4.2\jre\lib\rt.jar]

The first line indicates that the class came from the main JAR for the demo (assuming it was started with java -jar SwingSet2.jar). The second line indicates that the TableUI class was loaded from the rt.jar file that comes with the runtime located in the c:\j2sdk1.4.2\jre directory. (From there, the rt.jar file is located in the lib subdirectory.) Different implementations of the Java platform can have different formats here. The only requirement is that -verbose:class displays messages as classes get loaded and unloaded.

Let's see when classes are loaded, and how many classes are needed for the following simple program:

    public class Sample {
      public static void main(String args[]) {
        System.out.println("Hello, World");
      }
    }

Compile the Sample class. Then run it with the -verbose:class option enabled:

   java -verbose:class Sample

When you run the command, you'll see that this simple program requires the opening of five jar files (such as rt.jar) and the loading of almost 250 classes.

To see an example of a class unloading message, try the -verbose:class command line option with the RunItReload class shown in the August 19, 2003 Tech Tip titled Unloading and Reloading Classes.

The -verbose:gc option reports on each garbage collection event. This includes the time for garbage collection to run, and the before and after heap sizes. This is demonstrated in the following lines:

  [GC 27872K->26296K(42216K), 0.0069590 secs]
  [GC 28973K->26455K(42216K), 0.0036812 secs]
  [GC 29134K->26474K(42216K), 0.0016388 secs]
  [GC 29117K->26487K(42216K), 0.0008859 secs]
  [GC 29134K->26498K(42216K), 0.0009197 secs]
  [GC 29180K->26479K(42216K), 0.0008711 secs]
  [GC 29149K->26484K(42216K), 0.0008716 secs]

Like the output for -verbose:class, there is no requirement for output format, and it is subject to change without notice. The "GC" at the beginning indicates what kind of collection occurred. The number before the "->" is the heap occupancy before the collection. The number after the "->" is the heap occupancy after the collection. The number in parentheses is the currently allocated size of the heap. The seconds are the duration of the collection.

This information can be useful in debugging. For example, it could help you determine if garbage collection happened at a critical point in time, and might have caused a program to crash. This sometimes happens when mixing Java and C/C++ code with JNI, especially when there is an underlying bug on the C/C++ code side.

If you're ever curious about why it takes so long for an application to start, or if garbage collection in the middle of an operation appears to cause a problem, be sure to try out these command line options.

For additional information on these and other command line options, see the documentation on the java command specific to your platform:

  • Linux
  • Windows
  • Solaris

    .
    .
    Reader Feedback
    Excellent   Good   Fair   Poor  

    If you have other comments or ideas for future technical tips, please type them here:

    Comments:
    If you would like a reply to your comment, please submit your email address:
    Note: We may not respond to all submitted comments.

    Have a question about Java programming? Use Java Online Support.

    .
    .

    IMPORTANT: Please read our Terms of Use, Privacy, and Licensing policies:
    http://www.sun.com/share/text/termsofuse.html
    http://www.sun.com/privacy/
    http://developers.sun.com/dispatcher.jsp?uid=6910008


    Comments? Send your feedback on the Core Java Technologies Tech Tips to: http://developers.sun.com/contact/feedback.jsp?category=newslet

    Subscribe to other Java developer Tech Tips:

    - Enterprise Java Technologies Tech Tips. Get tips on using enterprise Java technologies and APIs, such as those in the Java 2 Platform, Enterprise Edition (J2EE).
    - Wireless Developer Tech Tips. Get tips on using wireless Java technologies and APIs, such as those in the Java 2 Platform, Micro Edition (J2ME).

    To subscribe to these and other JDC publications:
    - Go to the JDC Newsletters and Publications page, choose the newsletters you want to
    subscribe to and click "Update".
    - To unsubscribe, go to the
    subscriptions page, uncheck the appropriate checkbox, and click "Update".


    ARCHIVES: You'll find the Core Java Technologies Tech Tips archives at:
    http://java.sun.com/developer/JDCTechTips/index.html


    Copyright 2004 Sun Microsystems, Inc. All rights reserved.
    4150 Network Circle, Santa Clara, CA 95054 USA.


    This document is protected by copyright. For more information, see:
    http://java.sun.com/developer/copyright.html


    Java, J2SE, J2EE, J2ME, and all Java-based marks are trademarks or registered trademarks (http://www.sun.com/suntrademarks/) of Sun Microsystems, Inc. in the United States and other countries.

    Sun Microsystems,
Inc.
  • 'java UI' 카테고리의 다른 글

    File Connection Optiobal Package  (0) 2006.02.28
    [펌] DataSource의 복제를 통한 다중 플레이어 생성방법  (0) 2005.12.02
    jtable tutorial  (0) 2005.02.16
    The Eclipse runtime options  (0) 2005.02.15
    www.eclipse-plugins.info 의 순위  (0) 2005.02.12
    BEYOND THE BASICS OF JOPTIONPANE  (0) 2005.02.11
    Posted by 김용환 '김용환'

    댓글을 달아 주세요