이전 포스트에서 이클립스에서 class파일을 디컴파일하는 방법을 소개한 적이 있다.

헌데 간혹 jd-eclipse로 디컴파일이 되지 않는다는 분이 계셔서 확인해보았다.

class 파일을 열면 열리지 않고 에러문구만 다음과 같이

....could not be initialized... 라면서 재설치를 하라고 나온다... 

 

이런 문의가 있어서 테스트를 해봐도 이상이 없었는데

새로이 XP를 설치한 경우에야 동일 증상을 발견하고

그 이유를 알게 되었다.

이클립스 플러그인 외에 OS가 윈도우즈인 경우 (다른 OS는 상관없는 듯 ...)

 "Microsoft Visual C++ 2008 SP1 Redistributable Package" 가 설치되어 있어야 한다.

 

커스텀XP를 사용시 위 패키지 설치를 제한하는 경우가 있는데 이  라이브러리가 설치되지 않아

jd-eclipse가 초기화되지 않아서 발생한 문제였다.

 

참고로 이클립스 3.5 버젼에서 Equinox/p2 plug-in 을 설치하는 방법이 이전(3.4)와 조금 달라..

함께 끄적여 본다..

 

 

이클립스 3.5 버젼에서 Install Software 화면에서 하단의 Group items by category 항목이

기본적으로 체크되어 있는데 이 부분을 체크해제하면 위와 같이 Equinox p2 Provisioning 항목을 확인할 수 있다.

 

 

JOTM을 이용한 분산Transaction 처리

 

개요

Spring 등의 오픈소스프레임워크를 이용한 개발 프레젠테이션을 할 때 질문을 받았던 내용 중에 하나가무거운 EJB보다 필요한 기능만을 갖춘 가벼운 Spring등의 프레임워크를 쓰자는 것은 이해가 간다. EJB를 쓰는 주된 이유중에 하나인 분산처리 기능을 Spring등은 어떻게 처리하고 있는가?”

교과서적인 답변이랄까? Spring JTA를 이용한 분산처리 트랜잭션API을 지원하고 있습니다. -_- a

틀린 말은 아니지만 그 분의 질문은 JTA를 어떻게 사용할수 있는가라는 의도였던 것 같다. WAS 를 쓰면서도 EJB 만의 기능(앞서 언급한 분산처리기능)을 구현하거나 필요로 했던 프로젝트는 그다지 많지 않았다. 그래서 Spring등과 톰캣을 이용한 프로젝트들이 많이 생겨난 것이지만 사실 그렇기 때문에 Spring을 통해서도 충분히 분산처리가 가능합니다.라고 고객께 말은 드리지만 정작 분산처리기능이 필요한 경우에는 특히 분산트랜잭션 서비스를 지원하지 않은 서블릿컨테이너(톰캣)을 사용하는 경우에 JTA 를 어떻게 사용해야 하는지 개발자는 조금 더 알아야 하지 않을까?

JOTM(Java Open Transaction Manager)

 

두 개 이상의 자원에 동시에 접근하는데 Transaction이 필요한 경우가 있다. 예를 들어 결재정보를 저장하는 데이터베이스와 구매내역을 저장하는 데이터베이스가 다르다고 할때 이 두 데이터베이스에 접근하기 위한 DataSource는 다르지만 두 데이터베이스에 접근하는 코드는 단일 트랜잭션으로 처리되어야 한다. 웹로직이나 JBoss 등의 WAS는 자체적으로 분산트랜잭션서비스를 지원하지만 톰캣과 같은 서블릿컨테이너는 분산 트랜잭션을 지원하지 않는다. 만약 톰캣과 같은 분산트랜잭션을 지원하지 않은 컨테이너에서 구현해야 한다면 JOTM을 사용하면된다.

 

JOTM(Java Open Transaction Manager) ObjectWeb에서 제공하는 트랜잭션 관리자로서 JTA, JTS 등의 API를 지원하고 있으며 JOTM을 사용하면 기존의 JDBC 기반의 코드에 JTA를 이용한 트랜잭션 처리 코드를 손쉽게 적용할 수 있게 된다..

아래의 항목은 Spring에서 JOTM을 어떻게 사용하는지에 대하여 설명하고 있으며 순서에 따라 진행하면 된다.

 

1. JOTM library download  Jar 파일 설치

  - spring2.5를 다운받았다면 :jotm,jotm_jrmp_stubs.jar,xapool.jar webapplication classpath에 추가

  - JOTM site에서 download받게되면 ow_carol-all.jar를 찾아 webapplication classpath에 추가

 

2.spring에서 제공하는 JotmFactoryBean bean 설정

 

3.각각 사용할 database dataSource org.enhydra.jdbc.pool.StandardXAPoolDataSource를 이용하여 설정한다

 

4.ibatis를 사용할 경우 slqMapClient에 각각 사용할 dataSource property로 가지도록 설정한다

 

spring설정 file(일반적으로 application.xml)

 

  <!-- jotm 설정 -->

    <bean id="jotm"

        class="org.springframework.transaction.jta.JotmFactoryBean" />

 

    <!-- jotm property로 가지는 JtaTransactionManager설정 -->

    <bean id="transactionManager"

        class="org.springframework.transaction.jta.JtaTransactionManager"  p:userTransaction-ref="jotm" />

    <!-- StandardXAPoolDataSource를 이용한 postgresSQL dataSource설정  -->

    <bean id="postgresDBDataSource"  class="org.enhydra.jdbc.pool.StandardXAPoolDataSource"

destroy-method="shutdown">

        <property name="dataSource">

            <bean class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown">

                <property name="transactionManager" ref="jotm" />

                <property name="driverName" value="org.postgresql.Driver" />

                <property name="url" value="jdbc:postgresql://localhost:5432/testDb?charSet=UTF-8" />

            </bean>

        </property>

        <property name="user" value="test" />

        <property name="password" value="test" />

    </bean>

    

    <!-- StandardXAPoolDataSource를 이용한 oracle dataSource설정  -->

    <bean id="oracleDBDataSource"  class="org.enhydra.jdbc.pool.StandardXAPoolDataSource"

        destroy-method="shutdown">

        <property name="dataSource">

            <bean class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown">

                <property name="transactionManager" ref="jotm" />

                <property name="driverName" value="oracle.jdbc.driver.OracleDriver" />

                <property name="url" value="jdbc:oracle:thin:@127.0.0.1:1526:TEST" />

            </bean>

        </property>

        <property name="user" value="test" />

        <property name="password" value="test" />

    </bean>

    

    <!-- postgresSQL dataSource property로 하는 slqMapClient설정 -->

    <bean id="sqlMapClient"  class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">

       <property name="configLocation" value="/WEB-INF/config/sqlmap-config.xml"/>

       <property name="dataSource" ref="postgresDBDataSource"/>

    </bean>

    

    <!-- oracle dataSource property로 하는 slqMapClient설정 -->

    <bean id="oracleDbSqlMapClient"  class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">

       <property name="configLocation" value="/WEB-INF/config/sqlmap-config.xml"/>

       <property name="dataSource" ref="oracleDBDataSource"/>

    </bean>

    

    <!-- postgresSQL dataSource property로 하는 slqMapClient를 가지는 dao -->

    <bean id="postgresDbDao" class="test.dao.PostgresDbDao">

        <property name="sqlMapClient" ref="sqlMapClient" />    

    </bean>

    

    <!-- oracle dataSource property로 하는 slqMapClient를 가지는 dao -->

    <bean id="oracleDbDao" class="test.dao.OracleDbDao">

        <property name="sqlMapClient" ref="oracleDbSqlMapClient" />    

    </bean>

   <!-- The business Logic are autodetected POJOs labeled with the @Service annotaion -->

   <context:component-scan base-package="test.service" scoped-proxy="targetClass"  />

    <context:annotation-config />

    <!-- annotation으로 transcation를 선언 이때 transactionManager jotm transactionManager로 한다  -->

    <tx:annotation-driven transaction-manager="transactionManager"/>

 

iBatis 설정(일반적으로 sqlMap.xml)

 

  <insert id="insertTestInOracleDb" parameterClass="java.util.Map">

        INSERT INTO test_imsi ( name,age) VALUES (#name#,#age#)

    </insert>

    

    <insert id="insertTestInPostgresDb" parameterClass="java.util.Map">

        INSERT INTO test2_imsi ( name,age) VALUES (#name#,#age#)

    </insert>

 

dao (postgresSQL 사용, 여기서는 PostgresDbDao.java)

 

 public class PostgresDbDao extends SqlMapClientDaoSupport

{

    public void insertTestTable(Map<String,String> paramMap)

    {

        getSqlMapClientTemplate().insert("test.insertTestInPostgresDb",paramMap);

    }

}

 

dao (Oracle 사용, 여기서는 OracleDbDao.java)

 

 public class OracleDbDao extends SqlMapClientDaoSupport

{

    public void insertTestTable(Map<String,String> paramMap)

    {

        getSqlMapClientTemplate().insert("test.insertTestInOracleDb",paramMap);

    }

}

 

Service (비즈니스 로직 구현부)

 

 @Service

 @Transactional

 public class TestService

 {

    @Autowired

    private PostgresDbDao postgresDbDao;

    @Autowired

    private OracleDbDao oracleDbDao;

    

    public void jotmTransaction(Map<String,String> paramMap)

    {

        postgresDbDao.insertTestTable(paramMap);

        oracleDbDao.insertTestTable(paramMap);

    }

 }

 

 

자바에서 디컴파일을 할 필요가 있는 경우 사용하는 Decompiler로 jad를 이용하곤 했는데

그 jad를 이클립스에서 사용할 수 있도록 제공했던 jadclipse라는 플러그인이 있었습니다.

지금은 jd-eclipse라는 다른 이름으로 플러그인을 제공하고 있네요.

이전 update사이트로는 더이상 다운로드 받을수 없습니다.

저역시 이클립스 3.4 Ganymede를 사용하면서 이전 버젼이 동작되지 않아서 혹시 3.4버젼으로 업데이트가 되지 않았나 싶어

기존의  http://jadclipse.sf.net/update 로 업데이트를 받아보았지만 실패...

(다른 분들의 블로그에서는 3.4 버젼에서도 잘 동작된다고 하던데 ...-_-)

사이트로 직접 가보니 이런이런 http://java.decompiler.free.fr/jd-eclipse/update 로 바뀌었네요..

이름도 jadclipse에서 jd-eclipse로 바뀌었다는 사실..

그래도 설정메뉴는 window>preferences>java>JadClipse 로 예전과 동일합니다...

 

다음 3.4 버젼과 그 이전버젼의 설치방법은 아래에 소개합니다.

 

1단계 : Equinox/p2 plug-in 설치

  1. JD-Eclipse를 설치하기 위해서는 Equinox/P2 플러그인이 필요합니다. 먼저 설치를 해야합니다.
  2. 이클립스 메뉴 Help > Software Updates... 을 클릭하시면 Software Updates and Add-ons 팝업창이 뜨네요



  3. Available Software 탭을 선택합니다.
  4. Ganymede 항목을 펼칩니다.
  5. 하위리스트에서 Uncategorized 항목을 한번 더 클릭하여 펼칩니다.
  6. Equinox p2 Provisioning 항목을 선택하고 우측 상단의 Install... 버튼을 클릭합니다.
  7. 전 이미 설치가 되어있었지만 버젼이 달라서인지 설치에러가 나더라구요 그경우에는 installed software 탭을 선택후 업데이트를 진행하시면 됩니다.



  8. 잠시후 인스톨이 되면 활성화가 된 Finish 버튼을 클릭합니다.

2단계 : JD-Eclipse plug-in 설치하기

  1. 다시 Eclipse Help> Software Updates... 을 클릭하여 Software Updates and Add-ons 팝업창을 띄웁니다.
  2. Available Software 탭을 선택하시고.
  3. Add a new remote site 버튼을 클릭한 후 add JD-Eclipse plug-in을 추가합니다
    1. Add Site... 클릭하면 Add Site 팝업창이 뜹니다.
    2. Location 필드에 다음과 같이 http://java.decompiler.free.fr/jd-eclipse/update 라고  JD-Eclipse update 사이트주소를 입력후 OK 버튼을 클릭합니다



  4.  Software Updates and Add-ons 윈도우창에 JD-Eclipse update site가 표시되면, 다음과 같이 JD-Eclipse Plug-in 를 선택한 다음Install... 버튼을 클릭합니다.



  5. 진행후 다음 화면에서 Finish 버튼을 클릭합니다.
  6. Java Decompiler Eclipse Plug-in certificate 확인 페이지가 뜨는데 체크박스를 선택하고 OK 버튼 클릭.

JD-Eclipse plug-in이 성공적으로 설치가 된 경우에는 이클립스를 재구동하면 적용사항을 확인할 수 있다

비고.Eclipse 3.2, 3.3 의 경우

  1. 역시 이클립스 Help 메뉴 아래 Software Updates > Find and Install... 를 선택하면 Install/Update 팝업창이 뜹니다



  2. Install/Update 팝업창에서 Search for new features to install 옵션선택후 Next 버튼 클릭.
  3. new remote site 팝업창에서 JD-Eclipse plug-in 업데이트 주소를 입력합니다:
    1.  New Remote Site... 버튼을 클릭하면 New Update Site 팝업창이 뜹니다.
    2.  New Update Site 팝업창에서 Name 필드에는  JD-Eclipse Update Site 라고 입력합니다 
    3. URL 필드에는 http://java.decompiler.free.fr/jd-eclipse/update 라고 입력후 OK 클릭.



    4. Finish 버튼을 클릭하여 Updates 팝업창으로 돌아옵니다.
  4. Updates 창에서 JD-Eclipse Update Site 를 선택하고 Finish 버튼을 클릭.



  5. 다음화면에서 JD-Eclipse Update Site 를 선택후  Next 버튼 클릭.
  6. 역시 the license agreement를 확인하는 창에서 체크박스를 선택후 Next 버튼 클릭.
  7. Finish 버튼 클릭.
  8. Install All 버튼을 클릭. (끝)

다음 해야될것이 .class 파일클릭시 기본적으로 jadclipse 가 실행되도록 설정해줘야 합니다.

Windows> Preferences > General > Editors > File Associations 클릭하게 되면

모든 확장자가 기본적으로 취하게 되는 프로그램명들을 설정할수 있게 되어있는데 .class 파일을

클릭해서 아래에 jadclipse file view를 기본으로 사용하겠다고 오른쪽 default 클릭해서 셋팅합니다.

 

설정항목은 이클립스 window메뉴>preferences>java>JadClipse 에서 확인할 수 있습니다.

보통은 그대로 두시면 되는데

혹 안되신다면 path to decompiler 항목에 디컴파일러인 jad.exe가 있는 경로를 지정합니다.

jadClipse와 마찬가지로 jad를 다운받는곳이 바뀌었는지 링크가 걸리질 않습니다.

그래서 기냥 첨부파일로 올려드리구여. 압축을 임의의 폴더에 푸신후 경로를 지정하시면 됩니다.

(예 d:\dev\jad\jad.exe) 

 

혹 한글이 깨지시는 분은 window메뉴>preferences>java>JadClipse>Misc 에서 

Convert Unicode String into ANSI Strings 항목을 선택합니다.

사용방법은 jar파일내 class파일을 클릭하시면 디컴파일된 코드로 보실수 있습니다.(초간단)


 

 

2007년 8월과 9월에 썬 개발자 네트워크의 John O'Conner는 JavaFX 스크립트 프로그래밍 언어

(이 기사에서는 JavaFX 스크립트라고 줄여서 부름)를 시작하는 사용자에게 도움을 주고자

"학습 곡선 일지(Learning Curve Journal)"라는 제목의 시리즈를 기고했습니다.

 그 이후로 이 언어의 많은 중요한 부분이 개선되었습니다.

아마도 가장 중요한 변화는 JavaFX 스크립트의 초기 인터프리터 기반 버전을 대신하여 컴파일러 기반 버전을

사용할 수 있게 되었다는 점입니다. 학습 곡선 일지 시리즈의 1편, 2편 및 3편은 컴파일러 기반 버전의

언어 사용 방법을 보여주기 위해 업데이트 되었습니다.

최신 내용을 반영하여 다른 변경 사항도 적용되었습니다.

4편은 시리즈의 2편에서 시작된 JavaFX 이미지 검색 애플리케이션을 완결하는 새로운 부분입니다.

학습 곡선 일지의 앞 부분에서는 JavaFX 스크립트를 사용하여 Flickr에서 이미지를 검색하는

기존 이미지 검색 애플리케이션의 사용자 인터페이스(UI)를 재현했습니다.

결과 JavaFX 스크립트는 원래 UI와 완전히 똑같진 않지만 상당히 근접했습니다.

그림 1은 JavaFX 스크립트 구현으로 생성된 기본 UI를 보여줍니다.

 

그림 1. JavaFX 이미지 검색 애플리케이션 UI

 UI 구축에는 계층 구조적인 Swing 기반 접근 방법을 따랐습니다.

이 시리즈의 1편에서 언급한 것처럼 JavaFX 개발자는 앞으로 노드 기반 접근 방법을 사용할 것입니다.

이제 애플리케이션의 JavaFX 스크립트 버전을 완료하고 사용자가 Flickr 웹 사이트에서 이미지를 검색, 나열 및

표시할 수 있도록 하겠습니다. 완성된 JavaFX 스크립트 애플리케이션을 위해 NetBeans 프로젝트 다운로드를 받을 수 있습니다.


이미지 검색

구 현할 첫 번째 동작은 이미지 검색입니다.

사용자가 UI의 검색 필드에 검색어를 입력하면 애플리케이션은 Flickr 웹 사이트에서 이미지 검색을 시작합니다.

검색어와 매칭되는 이미지가 있으면 애플리케이션은 최대 100개의 매칭되는 축소판 이미지의 목록을 로드하여

UI의 Matched Images 영역에 선택 가능한 목록으로 표시합니다. 또한 진행 표시줄이 이미지 검색을 추적합니다.

기 존 이미지 검색 애플리케이션은 Matched Images 영역에 반환된 축소판 이미지의 목록을 제목과 함께 표시합니다.

우리는 JavaFX 스크립트 애플리케이션 목록에서 매칭되는 이미지의 반환된 제목만 보여주도록 단순화하겠습니다.

JavaFX 스크립트의 ListItem 구성요소는 현재 icon 속성을 갖지 않습니다.

따라서 현재 ListListItem 구성요소가 생성하는 목록은 이미지를 포함할 수 없습니다.

이미지 검색을 위해 ImageSearcherPhoto의 두 가지 JavaFX 스크립트 클래스를 생성했습니다.

또한 진행 표시줄을 위한 별도의 클래스도 생성했습니다. JavaFX 스크립트 패키지에 ProgressBar 구성요소는 아직 없습니다.

임시 해결책으로 학습 곡선 일지 시리즈에서 구축한 이미지 검색 UI에 Swing JProgressBar 구성요소로부터

JavaFX 스크립트 진행 표시줄을 생성하는 createProgressBar 함수를 포함했습니다.

우리는 이 함수를 자체 파일의 자체 클래스로 이동하기로 결정했습니다.

이는 애플리케이션의 주요 부분을 깔끔하게 만드는 이점이 있습니다.

따라서 애플리케이션에는 이제 4개의 파일이 있습니다.

  • Main.fx: 애플리케이션의 주요 부분을 제공합니다. UI를 표시하고 이미지 검색 및 가져오기를 호출합니다.
  • ImageSearcher.fx: 이미지 검색을 수행합니다.
  • Photo.fx: Flickr 사진을 나타냅니다.
  • TempProgressBar.fx: 진행 표시줄을 생성합니다.

다음은 이미지 검색을 호출하는 Main.fx의 코드입니다.

  var searcher = ImageSearcher {
      callback: function(photos:Photo[]):Void {
          thumbnailList.items = for(photo in photos) {
              ListItem {
                  text: photo.title
                  value: photo
              }
          };

          matchedImagePB.indeterminate= false;
      }
  };

  var search = function():Void {
      System.out.println("searching... {searchTextField.text}");
      matchedImagePB.indeterminate = true;
      searcher.search(searchTextField.text);
  };

  searchTextField.action=search;

사용자가 UI의 검색 필드에 검색어를 입력하면 ImageSearcher 클래스 내의 search 함수를 호출하는 작업을

트리거하고 검색어를 search 함수로 전달합니다.

변수에 함수가 지정된 것에 유의하십시오.

  var search = function():Void {...}
 

JavaFX 스크립트에서 함수는 변수에 지정되거나 매개 변수로써 다른 함수에 전달될 수 있는 1급 개체(first-class object)입니다.

또한 함수는 matchedImagePB의 indeterminate 등록 정보를 true로 설정합니다. 

  var matchedImagePB = TempProgressBar { };
  matchedImagePB.indeterminate = true;

TempProgressBar 클래스는 matchedImagePB 변수에 지정됩니다.

따라서 matchedImagePB의 indeterminate 등록 정보를 설정하는 것은 실질적으로

TempProgressBar 개체의 indeterminate 등록 정보를 설정하는 것입니다.

그 영향을 이해하기 위해 TempProgressBar 클래스를 살펴보겠습니다.


TempProgressBar 클래스

다음은 TempProgressBar 클래스입니다.

 package javafxscriptimgsearch2;

  import javafx.ext.swing.*;

  public class TempProgressBar extends Component {
      protected function createJComponent():javax.swing.JComponent {
          return new javax.swing.JProgressBar();
      }
      public attribute indeterminate:Boolean = false on replace {
          var prog = this.getJComponent() as javax.swing.JProgressBar;
          prog.setIndeterminate(indeterminate);
      }
}
클래스에는 createJComponent 함수와 indeterminate 속성이 있습니다. 
replace
트리거가 indeterminate 속성에 연결되어 있습니다.
      public attribute indeterminate:Boolean = false on replace {
          var prog = this.getJComponent() as javax.swing.JProgressBar;
          prog.setIndeterminate(indeterminate);
      }
 

애플리케이션의 주요 부분이 속성을 true로 설정하는 것과 같이 속성 값이 변경되면 트리거는 진행 표시줄을 생성합니다.

특히 트리거는 getJComponent() 함수를 사용하여 JavaFX 스크립트 구성요소로 캡슐화된 Swing JProgressBar

구성요소를 생성합니다. 트리거는 또한 JProgressBar 구성요소의 indeterminate 등록 정보를

true로 설정하여 검색 진행 중에 진행 표시줄이 계속 움직이도록 합니다.

트 리거는 JavaFX 스크립트의 강력한 기능 중 하나입니다. 트리거는 특정 조건 충족 시 코드 블록을 실행하도록 합니다.

또한 기존 Swing 구성요소의 재사용이 얼마나 쉬운지에도 유의하십시오.

Swing 구성요소를 사용하려면 JavaFX 스크립트로 간단한 래퍼(wrapper)를 작성하기만 하면 됩니다.


ImageSearcher 클래스

다음은 ImageSearcher 클래스입니다.


   package javafxscriptimgsearch2;

import javax.xml.parsers.*;
import org.xml.sax.helpers.DefaultHandler;
import java.lang.System;
import java.lang.Thread;
import java.lang.Runnable;
import javax.swing.SwingUtilities;

public class ImageSearcher {
public attribute callback: function(photos:Photo[]):Void;

public function search(search:String) {
var thread = new Thread(Runnable {
public function run():Void {
var photos:Photo[];

var handler = DefaultHandler {
public function startDocument() { }
public function startElement(uri:String, localName:String, qName:String , attributes:org.xml.sax.Attributes ) {
if(qName == "photo") {
var photo = Photo {
id: attributes.getValue("id")
server: attributes.getValue("server")
farm: attributes.getValue("farm")
title: attributes.getValue("title")
secret: attributes.getValue("secret")
};
insert photo into photos;
}
}
public function endElement(uri:String , localName:String , qName:String ) { }
public function endDocument() { }

};

var SEARCH_URL = "http://api.flickr.com/services/rest/?" +
"method=flickr.photos.search";
var key = "339db1433e5f6f11f3ad54135e6c07a9";
var MAX_IMAGES = 100;
var searchUrl = "{SEARCH_URL}&api_key={key}&per_page={MAX_IMAGES}&text={search}";
var url = new java.net.URL(searchUrl);
var is = url.openStream();
var factory = SAXParserFactory.newInstance();
var saxParser = factory.newSAXParser();
saxParser.parse(is, handler);

SwingUtilities.invokeLater(Runnable {
public function run():Void {

if(callback != null) {
callback(photos);
}
}
});
}
});
thread.start();
}
}
 

ImageSearcher 클래스는 애플리케이션에서 이미지 검색을 수행하는 search 함수의 래퍼(wrapper)입니다.

새 스레드를 시작하여 search 함수가 시작됩니다. 스레드 내에서 함수는 검색어와 매칭되는 이미지(Flickr에서는 사진)를 가져오기

위해 Flickr 사진 검색 웹 서비스를 호출합니다. 다음은 Flickr 서비스를 호출하는 코드입니다. 

   var SEARCH_URL = "http://api.flickr.com/services/rest/?" +
          "method=flickr.photos.search";
  var key = "339db1433e5f6f11f3ad54135e6c07a9";
  var MAX_IMAGES = 100;
  var searchUrl = "{SEARCH_URL}&api_key={key}&per_page={MAX_IMAGES}&text={search}";
  var url = new java.net.URL(searchUrl);
  var is = url.openStream();

호출은 Flickr API의 REST(Representational State Transfer) 버전을 사용합니다

(Flickr는 XML-RPC 및 SOAP 버전도 제공합니다). API에 전달되는 인수에는 API 키, 반환되는 이미지의 최대 갯수,

사용자가 지정한 검색어가 포함됩니다. 애플리케이션에서 최대 100개의 매칭되는 이미지 목록을 다운로드하고 싶으므로

이미지 최대 갯수를 100으로 설정했습니다. 사진 검색 서비스는 사진을 XML 문서로 반환하므로 문서를 분석하는 기법이 필요합니다.

이 애플리케이션에서는 분석 수행을 위해 SAX DefaultHandler를 사용했습니다.

   var handler = DefaultHandler {
public function startDocument() { }
public function startElement(uri:String, localName:String, qName:String , attributes:org.xml.sax.Attributes ) {
if(qName == "photo") {
var photo = Photo {
id: attributes.getValue("id")
server: attributes.getValue("server")
farm: attributes.getValue("farm")
title: attributes.getValue("title")
secret: attributes.getValue("secret")
};
insert photo into photos;
}
}
public function endElement(uri:String , localName:String , qName:String ) { }
public function endDocument() { }

};

 

각 Flickr 사진에 대해 DefaultHandler사진 개체를 인스턴스화하고 속성 값을 Flicker 사진의 해당 속성 값으로 설정합니다.

DefaultHandler는 그 다음 각 Photo 개체를 photos라는 시퀀스에 추가합니다.

학습 곡선 일지 3편: JavaFX 스크립트 함수에서 시퀀스는 동일한 유형을 갖는 개체의 순서별 목록을 나타냈습니다.

search 함수는 그 다음 callback을 호출하는 다른 스레드를 시작합니다.

 SwingUtilities.invokeLater(Runnable {
          public function run():Void {

              if(callback != null) {
                  callback(photos);
              }
          }
  }
 

SwingUtilities.invokeLater 메소드는 스레드의 Runnable 작업을 이벤트 디스패치 스레드에 놓습니다.


Callback 함수

ImageSearcher 클래스는 속성 유형이 함수인 callback이라는 속성을 갖습니다. 함수는 photos 시퀀스를 매개 변수로

받고 아무 것도 반환하지 않습니다.

   public attribute callback: function(photos:Photo[]):Void;

ImageSearcher 클래스가 인스턴스화되면(애플리케이션의 주요 부분에 발생) callback 함수는 UI의 Matched Images

영역에 표시하기 위해 제목의 목록을 구축합니다. 목록의 각 항목은 속성 값이 반환된 사진의 제목인 text 속성과

속성 값이 Photo 개체인 value 속성을 갖습니다. 다음 코드는 애플리케이션의 주요 부분 내에서

 ImageSearcher 클래스를 인스턴스화하고 callback 함수를 제공합니다. 

  var searcher = ImageSearcher {
       callback: function(photos:Photo[]):Void {
          thumbnailList.items = for(photo in photos) {
              ListItem {
                  text: photo.title
                  value: photo
              }
          };
           matchedImagePB.Indeterminate= false;
      }
  };

매칭되는 사진 목록을 구축한 후 callback 함수는 Matched Images 진행 표시줄의 indeterminate 등록 정보를

기본값인 false로 다시 설정합니다.


이미지 검색 수행

이미지 검색을 다루는 코드를 검토했으니 이제 작업을 살펴봅시다. 그림 2는 사용자가 검색어를 입력한 후 Search 필드와

Matched Images 진행 표시줄의 상태를 보여줍니다.


그림 2.
검색어 입력

애플리케이션이 매칭되는 이미지를 검색하는 동안 검색어를 기반으로 검색 중임을 나타내는 메시지가 나타납니다.

이 예제에서는 "searching... polar bear" 메시지가 나타납니다.

그림 3은 매칭되는 이미지의 반환된 제목 목록 일부를 보여줍니다.


그림 3. 이미지 검색 결과
검색 함수가 올바르게 작동합니다!
 
이미지 표시

구현할 다음 동작은 이미지 표시입니다.

사용자가 반환된 이미지 제목 목록에서 제목을 선택하면 애플리케이션은 해당 이미지를 Flickr 사이트에서 가져와

UI의 Selected Image 영역에 표시해야 합니다.

표시를 위해 이미지를 가져오도록 onChange 위임을 추가하는 List 클래스의 사용자 정의 하위 클래스인

PhotoList라는 클래스를 추가했습니다. 다음은 Main.fx 파일에서 PhotoList 가 인스턴스화되는 방법을 보여줍니다.


   class PhotoList extends List {
       public
attribute onChange:function(photo:Photo);
       public
attribute selectedPhoto:ListItem = bind selectedItem on replace {
           var
photo = selectedPhoto.value as Photo;
           if
(onChange != null) {
               onChange(
photo);
           
}
       
}
   
}
 
   var
thumbnailList = PhotoList {
       preferredSize:[
300, 230]
       hmax:
Layout.UNLIMITED_SIZE
       vmax
: Layout.UNLIMITED_SIZE
   
};


사용자가 목록에서 항목을 선택하면 애플리케이션은 PhotoList 개체의 selectedPhoto 속성을 선택된 항목으로 설정합니다.

이는 PhotoList 개체의 selectedPhoto 속성이 다음 표현식의 결과에 바인딩되었기 때문입니다. 

  selectedItem on replace {
      var photo = selectedPhoto.value as Photo;
  }
 

바인딩은 표현식의 결과를 변수와 연관시키는 것을 의미합니다. 표현식이 변경되면(이 경우 selectedItem가 변경됨) 변수 값은

변경됩니다(이 경우 PhotoListselectedPhoto 속성이 자동으로 업데이트됨).

바인딩은 JavaFX 스크립트의 또 다른 강력한 기능입니다. 바인딩을 사용하여 애플리케이션의 부분을 직접적이고

우아하게 동기화할 수 있습니다.

또한 사용자가 목록에서 항목을 선택하면 애플리케이션은 PhotoList 개체의 onChange 속성과 연관된 이미지 로더 함수를 호출합니다.

이 함수는 선택된 진행 표시줄의 indeterminate 등록 정보를 true로 설정하여 이미지를 가져오는 동안 계속 진행되도록 합니다.

그 다음 선택된 Photo 개체에서 해당 이미지를 가져오기 위해 loadFullImage 함수를 호출합니다.

 class PhotoList extends List {
      public attribute onChange:function(photo:Photo);
      ...
          if(onChange != null) {
              onChange(photo);
       }

  // configure the image loader
  var imageLoader = function(photo:Photo):Void {
      if(photo != null) {
          selectedImagePB.indeterminate = true;
          photo.loadFullImage(function():Void{
              selectedImageDisplay.icon = Icon { image: photo.fullImage };
              selectedImagePB.indeterminate = false;
          });
      }
  };

thumbnailList.onChange = imageLoader;
 

이미지 로더는 Selected Image 영역에 표시하기 위해 이미지를 설정하고 이미지를 가져온 후

선택된 진행 표시줄의 indeterminate 등록 정보를 다시 false로 설정합니다. 

  selectedImageDisplay.icon = Icon { image: photo.fullImage };
  selectedImagePB.indeterminate = false;
 


Photo 클래스

Photo 클래스를 살펴봅시다.

 

    package javafxscriptimgsearch2;

import javafx.scene.image.*;
import java.lang.*;
import javax.swing.SwingUtilities;
import javax.imageio.ImageIO;

public class Photo {
public attribute id:String;
public attribute server:String;
public attribute farm:String;
public attribute title:String;
public attribute secret:String;

private attribute image:Image = null;

public attribute fullImage:Image = null;

public attribute fullImageURL = bind "http://static.flickr.com/{server}/{id}_{secret}.jpg";

public function loadFullImage(
callback:function():Void
):Void {

if(image == null) {
var thread = new Thread(Runnable {
public function run():Void {
var strImageUrl = "http://static.flickr.com/{server}/{id}_{secret}.jpg";
System.out.println("loading: {strImageUrl}");
var buffImg = ImageIO.read(new java.net.URL(strImageUrl));

SwingUtilities.invokeLater(Runnable {
public function run():Void {
image = Image.fromBufferedImage(buffImg);
fullImage = image;
if(callback != null) {
callback();
}
}
});

}});
thread.start();
} else {
callback();
}

}
}
 

Photo 클래스는 Flickr에 저장된 사진과 연관시키는 XML 속성에 해당하는 몇 가지 속성을 갖습니다.

예를 들어 Photo 클래스의 id 속성은 Flickr에 저장된 사진의 id 속성에 해당합니다. 또한 클래스는 Flickr에서 사진을 가져오는

loadFullImage 함수도 제공합니다.

새 스레드를 시작하여 loadFullImage 함수가 시작됩니다.

스레드 내에서 함수는 특정 사진에 대해 사진 소스 URL을 구성한 다음 사진을 가져옵니다.

다음은 사진 소스 URL을 구성하고 사진을 가져오는 코드입니다

   var strImageUrl = http://static.flickr.com/{server}/{id}_{secret}.jpg
   var buffImg = ImageIO.read(new java.net.URL(strImageUrl));

loadFullImage 함수가 URL 구성을 위해 Photo 개체의 server, idsecret 속성을 사용하는 것에 유의합니다.

또한 이미지 로드를 위해 자바 imagio 패키지의 ImageIO.read 메소드를 사용했습니다.

함수는 JavaFX 스크립트 Image 클래스의 fromBufferedImage 메소드를 사용하여 가져온 사진을 Photo 개체의

image 속성에 지정합니다. 그런 다음 호출자(이 경우 애플리케이션의 주요 부분에 있는 이미지 로더)에게의 callback

호출하는 다른 스레드를 시작합니다.

   SwingUtilities.invokeLater(Runnable {
       public function run():Void {
           image = Image.fromBufferedImage(buffImg);
           fullImage = image;
           if(callback != null) {
               callback();
           }
       }
   }); 

SwingUtilities.invokeLater 메소드는 스레드의 Runnable 작업을 이벤트 디스패치 스레드에 놓습니다.


목록에 이미지 표시

애플리케이션의 이미지 표시 부분을 테스트해봅시다. 그림 4는 Matched Images 영역에서 이미지를 선택한 후

Selected Image 진행 표시줄의 상태를 보여줍니다.


그림 4. 표시할 이미지 선택

애플리케이션이 이미지를 가져오면 이미지의 사진 소스 URL을 식별하는 메시지를 표시합니다.

이 예제에서는 "loading: http://static.flickr.com/3234/2595583764_a2e6661d3a.jpg" 메시지가 나타납니다.

이미지 가져오기가 끝나면 애플리케이션은 "loaded" 메시지를 표시합니다.

그림 5는 UI의 Selected Image에 선택한 이미지가 표시된 완전한 UI를 보여줍니다.


그림 5. 표시된 이미지

애플리케이션의 이미지 가져오기 부분이 작동합니다. 애플리케이션도 의도대로 작동합니다.

완성된 JavaFX 스크립트 애플리케이션을 위해 NetBeans 프로젝트 다운로드를 받을 수 있습니다.

 

요약

이 학습 곡선 일지 시리즈에서는 JavaFX 스크립트 프로그래밍 언어

(이 시리즈에서는 JavaFX 스크립트라고 줄여서 부름)의 사용을 시작하는데 도움이 되는 몇 가지 기본 개념 및 기법을 소개했습니다.

 

시리즈의 1편에서는 간단한 JavaFX 애플리케이션을 만드는 방법을 소개했습니다.

2편에서는 풍부한 UI 생성을 위해 사용 가능한 JavaFX 라이브러리 내의 일부 클래스와 언어의 선택적 구문을 설명했습니다.

UI 구축에는 계층 구조적인 Swing 기반 접근 방법을 따랐습니다.

이 시리즈의 1편에서 언급한 것처럼 앞으로 JavaFX 개발자는 노드 기반 접근 방법을 사용할 것입니다.

노드 기반 접근 방법에서는 UI 구축을 위해 다른 JavaFX 라이브러리를 사용할 것입니다.

3편에서는 뷰와 데이터 모델 등의 애플리케이션 부분을 동기화하기 위해 사용 가능한 JavaFX 스크립트의 바인딩 기능과

JavaFX 스크립트 함수를 다뤘습니다.

4편(본 기사)에서는 웹 서비스 액세스를 위한 JavaFX 스크립트 사용 방법을 보여주었습니다.

그 과정 중에 FX 스크립트에서 Swing 클래스와 같은 자바 기술 슬래스의 액세스가 얼마나 쉬운지도 보여주었습니다.

또한 이 시리즈를 통해 코드 완성과 같은 기능이 어떻게 NetBeans IDE 6.1에서 JavaFX 애플리케이션의 빌드 및 실행을

단순화하는지도 볼 수 있었습니다. JavaFX Preview SDK를 사용하여 명령줄에서 JavaFX 애플리케이션을

빌드 및 실행할 수도 있습니다.JavaFX 포함 NetBeans IDE 6.1을 다운로드하여 설치하거나

JavaFX Preview SDK를 다운로드하여 JavaFX 스크립트를 시작하십시오.


자세한 정보
이 글의 영문 원본은 Learning Curve Journal, Part 4: Accessing a Web Service에서 보실 수 있습니다.
 
2007년 8월과 9월에 썬 개발자 네트워크의 John O'Conner는 JavaFX 스크립트 프로그래밍 언어
(이 기사에서는 JavaFX 스크립트라고 줄여서 부름)를 시작하는 사용자에게 도움을 주고자
"학습 곡선 일지(Learning Curve Journal)"라는 제목의 시리즈를 기고했습니다.

그 이후로 이 언어의 많은 중요한 부분이 개선되었습니다.
아마도 가장 중요한 변화는 JavaFX 스크립트의 초기 인터프리터 기반 버전을 대신하여 컴파일러 기반 버전을
사용할 수 있게 되었다는 점입니다. 이전의 학습 곡선 일지에서는 인터프리터 기반 버전 사용에 대해 설명했습니다.

업데이트된 학습 곡선 일지에서는 컴파일러 기반 버전의 언어 사용법을 보여줍니다. 최신 내용을 반영하여 다른 변경 사항도 적용되었습니다.

지난 학습 곡선 기사에서는 간단한 사용자 인터페이스(UI)를 구현하고 UI 시험이 성공적이었음을 확인했습니다.

결과 JavaFX 스크립트는 Flickr에서 이미지를 검색하는 이미지 검색 애플리케이션 구축을 위한

원래 자바 프로그래밍 언어 UI와 비슷하게 보였습니다. 그림 1은 결과적인 기본 프레임을 보여줍니다.

 


그림 1. 원래 UI를 복제한 JavaFX 이미지 검색 애플리케이션

선언적 JavaFX 스크립트 구문을 사용한 결과 코드는 자바 언어 UI의 이식을 위한 괜찮은 시작이었습니다.

그러나 유휴 상태의 프레임, 응답하지 않는 검색 필드, 비활성 진행 표시줄, 빈 목록 상자 및

빈 이미지 레이블에 대한 추가 작업이 필요합니다. 여기에서는 아무 일도 발생하지 않습니다.

현재까지는 활성 데이터모델에 아무 UI 요소도 연결되지 않았으며 사용자 상호작용에도 응답하지 않습니다.

예를 들어 Search 텍스트 필드는 입력한 문자를 받아서 보여주지만 아직 아무 것도 하지 않습니다.

이 골격 뿐인 UI에는 추가 작업이 필요합니다. 이를 위해 비활성 애플리케이션에서 필요한 작업을 수행하도록 하는 함수가 필요합니다.


함수

JavaFX 스크립트 함수는 자바 프로그래밍 언어 메소드와 비슷합니다.

이들 메소드와 마찬가지로 함수는 매개 변수와 반환 값을 갖습니다.

또한 속성 및 변수와 if-then, while 루프, for 루프 및 기타 조건문도 가질 수 있습니다. 다음은 몇 가지 유효한 함수의 예입니다. 

function z(a,b) {
      var x = a + b;
      var y = a - b;
      return sq(x) / sq (y);
 }

 function sq(n) {return n * n; }

 function main() {
      return z(5, 10);
  }

  function min(x1 : Number, x2 : Number ): Number {
      if (x1 < x2) {
        return x1;
      }else {
        return x2;
     }
 }



반환 값 유형이나 매개 변수 유형을 선언할 필요가 없습니다.

그러나 자바 언어 프로그래머인 저에게는 min 함수에서와 같이 유형을 사용하는 것이 익숙하므로

가능한 경우에는 항상 사용하곤 합니다. 매개 변수 유형을 선언하는 것은 명확성에 도움이 됩니다.

따라서 z 함수를 다음과 같이 다시 작성하겠습니다.


 

function z(a: Number, b: Number): Number {
   var x: Number = a + b;
   var y: Number = a - b;
   return sq(x) / sq (y);
}

return 키워드는 선택 사항입니다.

 function sq(n) {n*n;}

 

위 함수는 다음과 같습니다.

 function sq(n) {return n*n;}
함수는 function 키워드로 시작합니다. 그 뒤에는 함수 이름과 매개 변수 목록이 나옵니다. 

JavaFX 스크립트에서는 유형이 변수나 함수 이름 다음에 나옵니다.

예를 들면 b: Number 매개변수는 b 라는 인수의 유형이 Number라는 의미입니다.

마지막으로 함수는 Number를 반환하므로 이를 매개 변수 목록 뒤에 선언할 수 있습니다.

함수의 본문 앞뒤에는 자바 언어에서 메소드 본문을 둘러싸는 것과 같이 괄호가 있습니다.

함수는 매개 변수나 기타 참조 변수가 변경될 때마다 반환 값을 재평가합니다.

이 기능은 개체를 자주 변경될 수 있는 특정 값에 바인드하려는 경우 유용합니다.

바인딩에 대해서는 나중에 자세히 설명하겠습니다.

클래스에 대해 함수가 정의될 수도 있습니다. 다음은 Friends 클래스에 대해 정의된 함수의 예입니다.

import java.lang.System;
  import javafx.lang.Sequences;

  class Friends {
      attribute knownNames: String[];
      function sayHello(name: String): String {
          var index = Sequences.indexOf(knownNames,name);
          if (index >= 0) {
              return "Hello, {name}!";
              } else {
              return "Sorry, I can't talk to strangers.";
              }
      }
  }

  var buddies = Friends {
      knownNames: ["John", "Robyn", "Jack", "Nick", "Matthew",
      "Tressa", "Ruby"]
  };

  var greeting = buddies.sayHello("John");
  System.out.println(greeting);

이 작은 프로그램은 sayHello 메소드에 아는 이름을 입력하면 "Hello"라고 응답합니다.

그렇지 않은 경우엔 "can't talk to strangers"라고 합니다.

Friends 클래스에는 한 가지 속성과 속성을 사용하여 메시지를 반환하는 함수가 포함되어 있습니다.

Sequences 클래스를 사용하는 것에 유의합니다. 이 클래스는 시퀀스 조작을 위한 다양한 함수를 포함합니다.

시퀀스는 이 예제에서 아는 이름의 목록과 같이 개체의 순서별 목록을 나타냅니다.

SequencesindexOf 함수는 지정된 시퀀스에서 같은 값을 갖는 개체를 검색합니다.

여기에서 indexOf는 아는 이름 시퀀스에서 지정된 이름(이 예제에서는 "John")과 매칭되는 개체를 검색합니다.


반응적 UI 요소

UI 요소(JavaFX 스크립트 라이브러리에서는 노드)는 키 입력이나 마우스 클릭과 같은 사용자 상호작용에 응답할 수 있습니다.

위젯은 action, onMouseClicked, onKeyTyped 및 기타 이벤트 기반 속성을 갖습니다. 이들 속성과 함수를 연관시킬 수 있습니다.

예를 들어 함수를 TextFieldaction 속성과 연관시키면 해당 함수는 필드 내에서 Enter를 누를 때 실행됩니다.

Button 위젯의 동일한 action 속성은 사용자가 클릭할 때마다 활성화됩니다.

JavaFX 이미지 검색 애플리케이션과 관련된 함수가 필요하므로 UI 요소에 대한 이벤트 핸들러를 작성하기로 했습니다.

다음 애플리케이션은 두 개의 버튼과 하나의 레이블을 생성합니다.

Bigger 버튼을 누르면 레이블의 글꼴 크기가 증가하고 텍스트가 변경됩니다.

Smaller 버튼을 누르면 레이블의 글꼴 크기가 감소하고 텍스트가 변경됩니다.

이 애플리케이션에서는 계층 구조적인 Swing 기반 접근 방법을 따릅니다.

이 시리즈의 1편에서 언급한 것처럼 앞으로는 JavaFX 스크립트 개발자가 노드 기반 접근 방법을 사용하도록 할 것입니다.

 

 import javafx.ext.swing.SwingFrame;
  import javafx.ext.swing.BorderPanel;
  import javafx.ext.swing.FlowPanel;
  import javafx.ext.swing.Button;
  import javafx.scene.Font;
  import javafx.scene.HorizontalAlignment;
  import javafx.ext.swing.Label;

  var font = Font { size: 18 };

  class FontDataModel {
      attribute text: String;

      function increaseFontSize() {
         font = Font { size: font.size + 1 };
         text= "Font Test ({font.size})";
         }
      function decreaseFontSize() {
         font = Font { size: font.size - 1 };
         text= "Font Test ({font.size})";
      }
  }

  SwingFrame {
       var myFont = FontDataModel {
           text: "Font Test (18)"
        }

      content:
      BorderPanel {
          top: FlowPanel {
              alignment: HorizontalAlignment.LEADING
              content: [
                  Button { text:"Bigger"
                      action :
                      function() {
                           myFont.increaseFontSize();
                      }
              },

              Button { text:"Smaller"
                  action : function() {
                      myFont.decreaseFontSize();
                  }
              }

              ]
          }
          center:
              Label {
                  width: 200
                  font: bind font
                  text: bind myFont.text

          }

       }
       visible: true
  }

 

 

 이 코드를 잘라내어 JavaFX 애플리케이션에 바로 붙여넣을 수 있습니다. Preview 버튼을 사용하면 그림 2의 결과가 보입니다.


그림 2. 미리보기 기능을 사용하여 JavaFX 스크립트 언어를 대화형으로 시험

이 Bigger-Smaller 글꼴 애플리케이션은 텍스트 문자열 속성을 갖는 FontDataModel을 생성합니다.

애플리케이션은 FontDataModel 인스턴스를 생성하고 text 속성을 초기화합니다.

FontDataModel에도 increaseFontSizedecreaseFontSize라는 두 가지 함수가 있습니다.

이들 함수는 텍스트 속성을 변경하고 Font 클래스의 인스턴스를 생성하며 인스턴스의 글꼴 크기를 업데이트합니다.

왜 글꼴을 FontDataModel의 속성으로 지정하고 텍스트 속성과 같은 방법으로 함수에서 업데이트하지 않는지 궁금할 지도 모릅니다.

이러한 접근 방법은 Font가 변경할 수 없는 개체, 즉 원래 개체의 속성을 변경할 수 없기 때문에 사용할 수 없습니다.

개체의 인스턴스에서만 속성을 변경할 수 있습니다.

각 버튼은 연관된 함수를 포함하는 action 속성을 갖습니다.

예를 들어 Bigger 레이블이 있는 버튼은 myFont 변수의 increaseFontSize 함수를 호출합니다.

 Button { text:"Bigger"

       action :
      function() {
           myFont.increaseFontSize();
      }
   
}
 

버튼을 누를 때마다 글꼴 크기와 텍스트가 변경되는 것을 볼 수 있습니다.

그림 3은 Bigger 버튼을 두 번 눌렀을 때의 결과를 보여줍니다.


그림 3. 버튼을 클릭하면 텍스트와 글꼴 크기 변경

분명히 increaseFontSize 메소드는 글꼴과 텍스트를 변경합니다. 이를 위해 바인딩이라는 JavaFX 스크립트 기능을 사용했습니다.


뷰와 모델 바인딩
 

JavaFX 스크립트에는 하나의 속성이 다른 속성의 변경을 추적하도록 하는 bind 연산자가 있습니다.

하나의 속성을 다른 속성에 바인딩한다는 것은 바인딩된 속성이 대상 속성의 변경 사항을 항상 인지한다는 것을 의미합니다.

이 Bigger-Smaller 글꼴 애플리케이션에서는 Label이 글꼴과 텍스트의 변경 사항을 추적하도록 하려고 합니다.

이를 위해 Labelfont 속성을 Font 변수에 바인드하도록 bind 연산자를 사용했습니다.

또한 Labeltext 속성을 FontDataModeltext 속성에 바인드하도록 bind 연산자를 사용했습니다.

다음은 Label 선언입니다.

  Label {
      width: 200
      font: bind font
      text: bind myFont.text

  }
 

bind 연산자는 함수에도 사용할 수 있습니다. 함수는 인수나 참조 변수가 변경될 때마다 결과를 업데이트하므로

함수에의 바인딩은 단일 속성에의 바인딩과 마찬가지로 작용합니다.

사실 함수는 실제로 바인딩과 함께 사용하도록 설계되었습니다.

본문 내의 매개 변수 및 참조 변수를 모두 포함하는 모든 종속성을 자동으로 추적하는

재사용 가능한 하위 루틴으로의 바인딩을 리팩터링하기 위해 이들을 사용할 수 있습니다.

표 1에서 코드의 일부를 참조하십시오.

 

표1. 함수와 함께/함수 없이 바인드 사용
 함수 없이 바인드  함수와 함께 바인드
 import java.lang.System;

   class Data {

       attribute foo: Number;
       attribute baz: Number;
   }

   var data = Data {
       foo: 4
       baz: 7
   };

   var zoo = bind data.foo +
           data.baz + 10;
   System.out.println(zoo);
   data.baz = 12;
   System.out.println(zoo);
 import java.lang.System;

   class Data {
       attribute foo: Number;
       attribute baz: Number;
       function add(x, y, z): Number {
           return x+y+z;
       }
   }

   var data = Data {
       foo: 4
       baz: 7
   };

   var zoo = bind data.add(data.foo, data.baz, 10);
   System.out.println(zoo);
   data.baz = 12;
   System.out.println(zoo);
 출력:  출력:
21.0
26.0
21.0
26.0
 
요약

JavaFX 애플리케이션에 동작을 추가하기 위해 함수를 사용합니다. UI 구성요소의 속성은 함수에 매핑됩니다.

action, onMouseClickedonKeyTyped와 같은 UI 이벤트 처리를 위해 이들 함수를 정의할 수 있습니다.

함수에는 함수 본문 내에서 매개 변수 및 참조 변수를 재평가하는 추가적인 등록 정보가 있습니다.

bind 연산자를 사용하여 하나의 속성을 다른 속성에 연결할 수 있습니다.

이는 UI 위젯이 모델 속성을 추적하도록 할 때 특히 유용합니다.

뷰 속성을 모델 속성에 바인딩한다는 것은 모델과 뷰가 동일한 데이터로 항상 동기화됨을 의미합니다.

JavaFX 이미지 검색 애플리케이션의 UI에 아직 기능을 추가하지 않았지만 함수가 필요하다는 것을 알게 되었습니다.

검색 텍스트를 가져오기 위해서는 거의 확실히 함수를 사용해야 합니다.

같은 함수가 이미지를 가져오기 위해 Flickr 사이트에도 액세스할 것입니다.

또한 뷰를 기본 모델에 연결하기 위해 bind 연산자도 사용해야 할 것입니다.

이제 UI를 일부 기본 작업 및 함수에 연결하는 방법을 알게 되었습니다.

또한 UI를 기본 모델에 연결하기 위해 bind 연산자도 사용할 수 있습니다.

 

자세한 정보
이 글의 영문 원본은 Learning Curve Journal, Part 3: JavaFX Script Functions에서 보실 수 있습니다.
 
2007 년 8월과 9월에 썬 개발자 네트워크의 John O'Conner는 JavaFX 스크립트 프로그래밍 언어
(이 기사에서는 JavaFX 스크립트라고 줄여서 부름)를 시작하는 사용자에게 도움을 주고자
"학습 곡선 일지(Learning Curve Journal)"라는 제목의 시리즈를 기고했습니다.

그 이후로 이 언어의 많은 중요한 부분이 개선되었습니다.
아마도 가장 중요한 변화는 JavaFX 스크립트의 초기 인터프리터 기반 버전을 대신하여 컴파일러 기반 버전을
사용할 수 있게 되었다는 점입니다. 이전의 학습 곡선 일지에서는 인터프리터 기반 버전 사용에 대해 설명했습니다.

업데이트된 학습 곡선 일지에서는 컴파일러 기반 버전의 언어 사용법을 보여줍니다.
최신 내용을 반영하여 다른 변경 사항도 적용되었습니다.

사용자 인터페이스를 정의하기 위해 10년 가까이 자바 프로그래밍 언어를 사용해온 저는

JavaFX 스크립트를 처음 사용해보고 두 가지 환경 사이의 큰 차이점을 금방 느낄 수 있었습니다.

프로그래머는 자바 언어에서 사용자 인터페이스(UI) 정의를 위해 절차적 언어를 사용하지만

JavaFX Script에서는 UI 정의에 선언적 문을 사용할 수 있습니다.

이는 커다란 차이이며 여기에 적응하는 데는 약간의 시간과 노력이 필요할 수 있습니다.

UI 생성을 위한 새로운 선언적 스타일에 대해 알아보고자

기존 애플리케이션 UI를 자바 언어 구현에서 JavaFX 스크립트로 이식하기로 했습니다.

썬 개발자 네트워크자바 언어 허브에 있는 Swingworker 기사에서 만든 이미지 뷰어 애플리케이션을 선택했습니다.

 

원래 애플리케이션은 Java SE 6에서 SwingWorker 클래스의 사용 방법을 보여주기 위한 것이었지만

UI 자체는 JavaFX 스크립트로의 간편한 이전을 제공할 만큼 충분히 단순해 보입니다.


기존 사용자 인터페이스

기존 애플리케이션에서는 사용자가 유명한 Flickr 웹 사이트에서 이미지를 검색, 나열 및 표시할 수 있도록 했습니다.

사용자는 검색어를 입력할 수 있으며 애플리케이션은 REST API를 사용하여 매칭되는 축소판 이미지 목록을 Flickr에 쿼리합니다.

사용자는 축소판 이미지를 하나 선택하여 크고 상세한 이미지를 가져올 수 있습니다.

그림 1은 검색 결과가 나온 기존 애플리케이션을 보여줍니다.

 

그림 1. 검색 결과가 나온 애플리케이션 UI

이 UI는 위에서부터 아래로 다음 구성요소로 이루어져 있습니다.

  • 기본 프레임 창 컨테이너 
  • 검색 레이블 및 검색 텍스트 필드 
  • 검색 매칭 레이블 및 진행 표시줄
  • 매칭되는 축소판 이미지 목록과 짧은 설명 
  • 선택 레이블 및 진행 표시줄
  • 선택한 이미지를 보여주는 레이블 
     

UI는 JFrame, JLabel, JProgressBar, JScrollPaneJList.와 같은 일반 Swing 구성요소로 이루어집니다.

JList 구성요소는 축소판 이미지와 제공되는 짧은 설명을 표시하기 위한 사용자 정의 렌더러를 갖지만 여전히 상대적으로 간단한 UI로서

JavaFX 스크립트의 선언적 UI 측면을 조사하는 데 도움이 될 것입니다.

전체 애플리케이션의 구현을 시도해 보겠지만 현재로는 기존 UI와 적당히 비슷한 정도로도 충분합니다.

작동하는 데모처럼 극적이진 않겠지만 그림 2에 나온 비활성 UI는 JavaFX 스크립트의 선언적 UI에 대한 초기 목표를 보여줍니다.

 

그림 2. 애플리케이션 UI

원래 UI는 NetBeans IDE 6.1과 Matisse GUI 편집기를 사용하여 구현했습니다.

Swingworker 기사에서 모든 원래 코드 및 생성된 UI 주변의 코드를 다운로드 받을 수 있습니다.

코드에서 이 UI를 생성하기 위해 NetBeans IDE가 GroupLayout를 어떻게 사용했는지 볼 수 있습니다.

 

private void initComponents() {
    lblSearch = new javax.swing.JLabel();
    txtSearch = new javax.swing.JTextField();
    lblImageList = new javax.swing.JLabel();
    scrollImageList = new javax.swing.JScrollPane();
    listImages = new JList(listModel);
    lblSelectedImage = new javax.swing.JLabel();
    lblImage = new javax.swing.JLabel();
    progressMatchedImages = new javax.swing.JProgressBar();
    progressSelectedImage = new javax.swing.JProgressBar();

    setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
    setTitle("Image Search");
    lblSearch.setText("Search");
    lblImageList.setText("Matched Images");

    // ...
    // event listeners, models, and cell renderers removed for this example
    //

    lblSelectedImage.setText("Selected Image");

    lblImage.setBorder(javax.swing.BorderFactory.createLineBorder(
            new java.awt.Color(204, 204, 204)));
    lblImage.setFocusable(false);
    lblImage.setMaximumSize(new java.awt.Dimension(500, 500));
    lblImage.setMinimumSize(new java.awt.Dimension(250, 250));
    lblImage.setOpaque(true);
    lblImage.setPreferredSize(new java.awt.Dimension(500, 250));

    javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
    getContentPane().setLayout(layout);
    layout.setHorizontalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
            .addContainerGap()
            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                .addComponent(lblImage, javax.swing.GroupLayout.Alignment.LEADING,
                        javax.swing.GroupLayout.DEFAULT_SIZE, 462, Short.MAX_VALUE)
                .addComponent(scrollImageList, javax.swing.GroupLayout.DEFAULT_SIZE,
                        462, Short.MAX_VALUE)
                .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addComponent(lblImageList)
                        .addComponent(lblSelectedImage))
                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addComponent(progressMatchedImages, javax.swing.GroupLayout.DEFAULT_SIZE,
                                350, Short.MAX_VALUE)
                        .addComponent(progressSelectedImage, javax.swing.GroupLayout.DEFAULT_SIZE,
                                350, Short.MAX_VALUE)))
                .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
                    .addComponent(lblSearch)
                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                    .addComponent(txtSearch, javax.swing.GroupLayout.DEFAULT_SIZE,
                            411, Short.MAX_VALUE)))
            .addContainerGap())
    );
    layout.setVerticalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGroup(layout.createSequentialGroup()
            .addContainerGap()
            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                .addComponent(lblSearch)
                .addComponent(txtSearch, javax.swing.GroupLayout.PREFERRED_SIZE,
                        javax.swing.GroupLayout.DEFAULT_SIZE,
                        javax.swing.GroupLayout.PREFERRED_SIZE))
            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addComponent(lblImageList)
                .addComponent(progressMatchedImages, javax.swing.GroupLayout.PREFERRED_SIZE,
                        javax.swing.GroupLayout.DEFAULT_SIZE,
                        javax.swing.GroupLayout.PREFERRED_SIZE))
            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
            .addComponent(scrollImageList, javax.swing.GroupLayout.PREFERRED_SIZE, 235,
                    javax.swing.GroupLayout.PREFERRED_SIZE)
            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addComponent(lblSelectedImage)
                .addComponent(progressSelectedImage, javax.swing.GroupLayout.PREFERRED_SIZE,
                        javax.swing.GroupLayout.DEFAULT_SIZE,
                        javax.swing.GroupLayout.PREFERRED_SIZE))
            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
            .addComponent(lblImage, javax.swing.GroupLayout.DEFAULT_SIZE, 305, Short.MAX_VALUE)
            .addContainerGap())
    );
    pack();
} 

 

 

NetBeans IDE를 사용한 UI 레이아웃은 쉽습니다. 드래그 앤 드롭이면 충분합니다.
이 예제에서 NetBeans IDE 6.1은 여러 가지 호스트 플랫폼에서 정확한 크기, 위치 및 구성요소의 간격을 제공하는 javax.swing.GroupLayout을 사용하여 UI 코드를 생성했습니다.
결과 코드는 그다지 읽기 쉽진 않지만 도구 지원이 뛰어나 레이아웃 코드를 직접 수동으로 작업할 필요가 없습니다.

 
선언적 JavaFX 스크립트 인터페이스

JavaFX 스크립트용의 설계 도구가 개발 중이지만 아직은 사용할 수 없습니다.
그러나 JavaFX 스크립트 플러그인이 포함된 NetBeans IDE 6.1의 미리보기 기능을 사용하면
수동으로 UI 코드를 입력하고 결과를 즉시 볼 수 있습니다.

이 인터페이스에 필요한 UI 구성요소는 javafx.ext.swing 패키지 및 javafx.scene으로 시작하는

다양한 패키지에 들어 있습니다. UI 구축은 계층 구조적인 Swing 기반 접근 방법을 따릅니다.

이 시리즈의 1편에서 언급한 것처럼 앞으로 JavaFX 개발자는 노드 기반 접근 방법을 사용할 것입니다.

노드 기반 접근 방법으로 UI를 구축하면 javafx.application 클래스의 일부 클래스가 필요할 것입니다.

JavaFX 스크립트는 패키지 구조 및 가져오기 문을 지원한다는 점에서 자바 언어와 유사합니다.

구성요소에 대해 공부하는 동안은 전체 패키지를 가져오는 대신 한 번에 하나씩 특정 구성요소를 가져오겠습니다.

이는 매우 지루하지만 하나씩 사용하게 함으로써 패키지에 어떤 구성요소가 있는지 보여줍니다.

 

JavaFX 스크립트 구성요소는 height, width, textcontent와 같은 속성을 갖습니다.

content 속성은 자녀 구성요소를 갖습니다. 구성요소에 따라 content 속성은 array로 선언되는

여러 개의 구성요소를 포함할 수 있습니다. 이미지 검색 애플리케이션을 위해 사용자 인터페이스를 선언할 때는

JavaFX 스크립트 구성요소의 선택 및 사용 후 속성을 설정합니다.

예를 들어 다음의 짧은 스크립트는 빈 프레임을 정의합니다. 이 코드는 컨텐츠가 없는 프레임 컨테이너를 생성합니다.

import javafx.ext.swing.SwingFrame;

  SwingFrame {
      title: "JFX Image Search"
      height: 500
      width: 500
      visible: true
  }
 

Swing의 JFrame에 해당하는 JavaFX 스크립트는 javafx.ext.swing.SwingFrame입니다.

title 속성은 프레임에 나타나는 텍스트인 창 프레임 제목을 선언합니다.

heightwidth 속성은 픽셀 단위로 크기 규격을 정의합니다.

마지막으로 visible 속성은 Swing의 JFrame 클래스 setVisible 메소드와 유사하게 프레임의 가시성 여부를 선언합니다.


Border Panel 및 Flow Panel
 

javafx.ext.swing 패키지에는 SwingFrame, Label, BorderPanel, FlowPanelList와 같은 구성요소가 포함됩니다.

이러한 이름은 일반적인 Swing 구성요소 같으므로 대상 UI 구현에 이들을 먼저 사용해보겠습니다.

javafx.scene 패키지의 HorizontalAlignment 구성요소와 javafx.scene.paint 패키지의 Color 구성요소도 사용했습니다.

그러나 JavaFX 스크립트 패키지에 ProgressBar 구성요소는 아직 없습니다.

따라서 진행 표시줄을 생성하는 함수를 코딩했습니다. 이 시리즈의 3편에서는 JavaFX 스크립트 함수를 검토합니다.

BorderPanelFlowPanel 등의 구성요소와 진행 표시줄의 함수를 사용하기로 결정하고 다음

JavaFXImageSearchUI1.fx 코드를 생성했습니다.

 

package com.sun.demo.jfx;

  import javafx.ext.swing.SwingFrame;
  import javafx.ext.swing.BorderPanel;
  import javafx.ext.swing.FlowPanel;
  import javafx.ext.swing.Label;
  import javafx.ext.swing.TextField;
  import javafx.ext.swing.List;
  import javafx.ext.swing.Component;
  import javafx.scene.paint.Color;
  import javafx.scene.HorizontalAlignment;
  import java.awt.Dimension;

  function createProgressBar(preferredSize:Integer[]) :Component {
      var jprogressbar = new javax.swing.JProgressBar();
      var comp = Component.fromJComponent(jprogressbar);
      comp.preferredSize = preferredSize;
      comp;
  }

  SwingFrame {
      title: "JFX Image Search"
      content: BorderPanel  {

          top: FlowPanel {
              alignment: HorizontalAlignment.LEFT
              content: [
              Label {
                  text: "Search"
                  },
              TextField {
                  columns: 50
              }
              ]
          }
          center: BorderPanel {
              top: FlowPanel {
                  alignment: HorizontalAlignment.LEFT
                  content: [
                  Label {
                      text: "Matched Images"

                      },
                  createProgressBar([360, 20])
                  ]
              }
              center: List {
                  preferredSize: [100, 200]
              }
              bottom: FlowPanel {
                  alignment: HorizontalAlignment.LEFT
                  content: [
                  Label {
                      text: "Selected Image"
                      },
                  createProgressBar([365, 20])
                  ]
              }
          }
          bottom: Label {
                  preferredSize: [400, 300]

          }

      }
      visible: true
  }

 

NetBeans IDE 6.1에 프로젝트를 생성한 후에 JFXImageSearchUI1.fx 파일에 위의 코드를 입력했습니다. 
미리보기 버튼을 클릭하면 그림 3과 같은 결과가 나타납니다.

그림 3. JavaFX 이미지 검색 UI -- 첫 번째 시도


프레임의 컨텐츠는 BorderPanel 구성요소로, top 속성은 FlowPanel 구성요소에 지정되고
center 속성은 다른 BorderPanel 구성요소에 지정되며 bottom 속성은 Label 구성요소에 지정되었습니다.
FlowPanel 구성요소는 content 등록 정보를 갖습니다. 이 등록 정보에 하나 이상의 구성요소를 넣을 수 있습니다.
여러 개의 구성요소를 삽입할 때는 array를 정의하는 괄호 속에 구성요소를 넣어야 합니다.
다음과 같이 쉼표를 사용하여 컨텐츠 array에서 개별 구성요소를 구분합니다.

content: [
  Label {
     text: "Search"
     },
  TextField {
     columns: 50
  }
  ]
 

상단 FlowPanel에는 Label 구성요소와 TextField 구성요소가 중첩되어 있습니다.

FlowPanel 의 방향 속성은 HorizontalAlignment.LEFT입니다.

이는 FlowPanel 내의 구성요소를 가로와 왼쪽으로 정렬합니다.

가운데의 BorderPanel은 이 영역의 상단에 가로로 정렬된 레이블과 진행 표시줄을, 중앙에 목록을,

하단에 다른 레이블과 진행 표시줄을 레이아웃합니다. 프레임의 하단에는 레이블이 들어갑니다.

FlowPanel 구성요소는 레이블-구성요소 쌍을 만들기에 좋습니다.

여기에서는 여러 개의 FlowPanel을 사용하여 레이블과 TextField 등의 구성요소를 묶었습니다.

createProgressBar 함수는 JavaFX 스크립트를 사용하여 Swing 구성요소로부터

javafx.gui 구성요소를 생성하는 방법을 보여줍니다.

여기에서는 Swing JProgressBar 구성요소로부터 JavaFX 스트립트 진행 표시줄을 생성했습니다.

function createProgressBar(preferredSize:Integer[]) :Component {
          var jprogressbar = new javax.swing.JProgressBar();
          var comp = Component.fromJComponent(jprogressbar);
          comp.preferredSize = preferredSize;
          comp;
  }
 

첫 번째 시도에서 UI는 상당히 잘 작동하지만 원래 UI를 제대로 재현하지는 못합니다. 그래서 다른 접근 방법을 시도해 보겠습니다.


클러스터
 

원래 UI를 복제하려는 두 번째 시도에서는 JavaFX 스크립트 ClusterPanel 구성요소를 활용하겠습니다.

이 구성요소를 사용하여 프레임 내에서 구성요소를 클러스터할 수 있습니다.

JavaFX 스크립트에는 ClusterPanel 내에서 구성요소를 순서대로나

병렬로 정리하기 위해 사용할 수 있는 SequentialClusterParallelCluster도 포함됩니다.

진행 표시줄, 검색 텍스트 필드, 축소판 이미지 목록 및 선택된 이미지 표시 영역의 최대 너비 및 높이를 설정하기 위해

JavaFX 스크립트 Layout 구성요소도 활용하기로 결정했습니다.

Layout 구성요소는 UNLIMITED_SIZE 등의 레이아웃 관련 상수를 제공합니다.

UI의 두 번째 버전은 다음 JFXImageSearchUI.fx 파일에 코딩되었습니다.


   package com.sun.demo.jfx;

import javafx.ext.swing.Component;
import javafx.ext.swing.SwingFrame;
import javafx.ext.swing.Label;
import javafx.ext.swing.TextField;
import javafx.ext.swing.List;
import javafx.ext.swing.Cluster;
import javafx.ext.swing.Layout;
import javafx.ext.swing.ClusterPanel;
import javafx.ext.swing.SequentialCluster;
import javafx.ext.swing.ParallelCluster;
import javafx.scene.paint.Color;
import java.awt.Dimension;
import java.lang.System;

import javax.swing.border.LineBorder;

function createProgressBar() :Component {
var jprogressbar = new javax.swing.JProgressBar();
var comp = Component.fromJComponent(jprogressbar);
comp.hmax = Layout.UNLIMITED_SIZE;
comp;
}

var searchLabel = Label {
text: "Search:"

}
var searchTextField = TextField {
hmax: Layout.UNLIMITED_SIZE
columns: 50
}

var matchedImageLabel = Label {
text: "Matched Images"
}
var matchedImagePB = createProgressBar();


var thumbnailList = List {
preferredSize:[300, 230]
hmax: Layout.UNLIMITED_SIZE
vmax: Layout.UNLIMITED_SIZE
}

var selectedImageLabel = Label {
text: "Selected Image"
}
var selectedImagePB = createProgressBar();

var selectedImageDisplay = Label {
preferredSize: [400,300]
hmax: Layout.UNLIMITED_SIZE
vmax: Layout.UNLIMITED_SIZE
}

selectedImageDisplay.getJComponent().setOpaque(true);
selectedImageDisplay.getJComponent().setBackground(Color.WHITE.getAWTColor());
selectedImageDisplay.getJComponent().setBorder(new LineBorder(Color.BLACK.getAWTColor(), 1, true));

SwingFrame {
title: "JavaFX Image Search"
content:
// main panel within the frame
ClusterPanel {

hcluster: SequentialCluster {
content: [
ParallelCluster{ // mainCol
resizable: true
content: [
SequentialCluster{
content: [
ParallelCluster { //searchLabelCol
content: searchLabel
},
ParallelCluster { //searchTextFieldCol
resizable: true
content: searchTextField
}
]},
SequentialCluster {
content: [
ParallelCluster { //lblCol
content: matchedImageLabel
},
ParallelCluster { //progressBarCol
resizable: true
content: matchedImagePB
}
]},
thumbnailList,
SequentialCluster {
content: [
ParallelCluster { //lblCol
content: selectedImageLabel
},
ParallelCluster { //progressBarCol
resizable: true
content: selectedImagePB
}
]},
selectedImageDisplay
]
}
]

}

vcluster: SequentialCluster {
content: [
ParallelCluster{ //searchRow
content: SequentialCluster {
content: [
ParallelCluster { // row
content: [searchLabel, searchTextField]
}
]
}
},
ParallelCluster{ // matchedProgressRow
content: SequentialCluster {
content: [
ParallelCluster { // row
content: [matchedImageLabel, matchedImagePB]
}
]
}
},
ParallelCluster{ // thumbNailRow
resizable:true
content: thumbnailList
},
ParallelCluster{ // selectedProgressRow
content: SequentialCluster {
content: [
ParallelCluster { // row
content: [selectedImageLabel, selectedImagePB]
}
]
}
},
ParallelCluster{ // imageRow
content: selectedImageDisplay
}

]
}

}
visible: true
}


 
이 코드의 결과는 훨씬 보기 좋습니다.
그림 4에 나온 것처럼 구성요소는 이제 프레임의 왼쪽과 오른쪽으로 완벽하게 정렬되었습니다.
 

그림 4. JavaFX 이미지 검색 UI -- 두 번째 시도


 

프레임의 주 컨텐츠는 ClusterPanel 구성요소입니다.
ClusterPanel 내에서 SequentialCluster 구성요소 그룹의 구성요소는 모두 순서대로 있습니다.
ParallelCluster 구성요소 그룹의 구성요소는 병렬로 있습니다.
예를 들어 다음은 구성요소를 프레임의 상단 영역에 정리합니다. 검색 레이블과 검색 텍스트 필드를 병렬 열로 클러스터합니다.


 
 hcluster: SequentialCluster {
      content: [
          ParallelCluster{ // mainCol
              resizable: true
              content: [
                  SequentialCluster{
                      content: [
                          ParallelCluster {  //searchLabelCol
                              content: searchLabel
                          },
                          ParallelCluster { //searchTextFieldCol
                              resizable: true
                              content: searchTextField
                          }
              ]},
 

SequentialClusterSequentialClusterParallelCluster와 같은 ClusterElement 구성요소를 지정할 수 있는

content 속성을 갖습니다. ParallelCluster 구성요소는 크기 조정이 가능하므로 필요에 따라 프레임 너비를 채웁니다.

인터페이스의 나머지도 같은 패턴을 따릅니다. 인터페이스의 각 5개 영역 내에서 구성요소는 SequentialCluster 구성요소 내에서 ParallelCluster 구성요소를 사용하여 그룹화 및 정리됩니다.

예를 들어 다음 코드는 매칭되는 이미지 레이블과 매칭되는 이미지 진행 표시줄을 병렬 열로 클러스터합니다.

클러스터 다음에는 검색과 매칭되는 이미지의 축소판 목록이 나옵니다.


 
SequentialCluster {
      content: [
          ParallelCluster {  //lblCol
              content: matchedImageLabel
          },
          ParallelCluster { //progressBarCol
              resizable: true
              content: matchedImagePB
          }
      ]},
  thumbnailList,
 

한 가지 주목할 점은 javafx.ext.swing 패키지의 Label 구성요소가 테두리 특성, 불투명도 또는 배경 색상의 설정을 위한 속성을

현재 지원하지 않는다는 것입니다. 따라서 이들 설정을 위해 getJComponent 함수에 대한 Label 구성요소의 지원을 활용했습니다.

함수는 JavaFX 스크립트 구성요소로 캡슐화된 Swing jComponent를 반환합니다.

이 경우에는 Swing Label 구성요소를 반환합니다. 다음 코드를 사용하여 필요한 레이블 속성을 정의할 수 있습니다.


var selectedImageDisplay = Label {
         ...
  }

  selectedImageDisplay.getJComponent().setOpaque(true);
  selectedImageDisplay.getJComponent().setBackground(Color.WHITE.getAWTColor());
  selectedImageDisplay.getJComponent().setBorder(new LineBorder(Color.BLACK.getAWTColor(), 1, true));
 
설계 도구 없이 이미지 검색 사용자 인터페이스를 복제하는 것에 대해 처음에 걱정했던 것과 달리 가장 유용하고 필요한 기능은 
빠르고 쉽게 액세스가 가능합니다. 또한 NetBeans IDE용 JavaFX 플러그인은 구성요소를 사용하여 작업할 때 사용 가능한
속성을 띄우는 문맥 인식 코드 완성을 제공합니다. 코드 완성을 사용하면 UI의 구현이 처음 생각처럼 어렵지만은 않습니다.
그림 5는 IDE에서 Ctrl+spacebar를 입력할 때 활성화되는 일부 팝업 옵션을 보여줍니다.


그림 5. 옵션


요약
 

UI 생성을 위한 선언적 구문을 살펴보기 위해 기존 애플리케이션의 UI를 이식했습니다.

원래 애플리케이션에서는 구성요소의 배치 및 정렬에 Swing의 GroupLayout을 사용했습니다.

NetBeans IDE 6.1은 아직 JavaFX 스크립트를 위한 그래픽 설계 도구를 지원하지 않지만

수동으로 인터페이스를 레이아웃하는 것은 처음 걱정했던것 만큼 어렵지 않았습니다.

ClusterPanel, SequentialClusterParallelCluster 구성요소의 조합을 통해

JavaFX 스크립트 구현은 원래 UI와 사실상 똑같아 보입니다.

이들 조합에 NetBeans IDE용 JavaFX 플러그인 및 문맥 인식 코드 완성이 더해져 작업은 더욱 쉬워졌습니다.


자세한 정보


이 글의 영문 원본은 # Learning Curve Journal, Part 2: Declarative User Interfaces에서 보실 수 있습니다.
 
2007년 8월과 9월에 썬 개발자 네트워크의 John O'Conner는 JavaFX 스크립트 프로그래밍 언어(이 기사에서는 JavaFX 스크립트라고 줄여서 부름)를 시작하는 사용자에게 도움을 주고자 "학습 곡선 일지(Learning Curve Journal)"라는 제목의 시리즈를 기고했습니다.

그 이후로 이 언어의 많은 중요한 부분이 개선되었습니다. 아마도 가장 중요한 변화는 JavaFX 스크립트의 초기 인터프리터 기반 버전을 대신하여 컴파일러 기반 버전을 사용할 수 있게 되었다는 점입니다. 이전의 학습 곡선 일지에서는 인터프리터 기반 버전 사용에 대해 설명했습니다. 업데이트된 학습 곡선 일지에서는 컴파일러 기반 버전의 언어 사용법을 보여줍니다. 최신 내용을 반영하여 다른 변경 사항도 적용되었습니다.

이 전과 마찬가지로 시리즈의 1편은 JavaFX 프로그램, 즉 JavaFX 스크립트 언어로 쓰여진 간단한 프로그램으로 시작합니다. JavaFX 스크립트에서의 프로그래밍을 위한 환경 설정 방법과 JavaFX 프로그램 빌드 및 실행 방법을 배우게 됩니다. 2편은 JavaFX 스크립트에서 사용 가능한 선언적 코딩 스타일에 중점을 둡니다. 이러한 스타일이 어떻게 그래픽 애플리케이션을 더욱 단순하고 직관적으로 만들 수 있는지 볼 수 있을 것입니다. 3편에서는 JavaFX 프로그램에서 작업 구현을 위한 JavaFX 스크립트 함수의 사용 방법을 보여줍니다. 4편에서는 웹 서비스 액세스를 위한 JavaFX 스크립트 사용 방법을 보여줍니다. 그 과정 중에 FX 스크립트에서 Swing 클래스와 같은 자바 기술 슬래스의 액세스가 얼마나 쉬운지도 보여줍니다.

JavaFX 스크립트는 개발자가 동적인 그래픽 컨텐츠 생성에 사용할 수 있는 새로운 스트립팅 언어입니다. 데스크탑에서 언어는 Swing 사용자 인터페이스(UI) 툴킷과 자바 2D API를 편리하게 사용할 수 있는 라이브러리를 제공합니다. Swing 또는 자바 2D를 대체하는 것이 아니고 풍부한 컨텐츠 개발자가 이들 API에 더욱 쉽게 액세스할 수 있도록 하는 것이 목적입니다. 모바일 시스템과 같은 다른 환경에서 JavaFX 스크립트는 Swing 이외의 사용자 인터페이스 기술을 사용합니다. JavaFX 스크립트를 사용하여 여러 가지 플랫폼과 운영 환경에서 실행되는 시각적으로 풍부한 애플리케이션을 만들 수 있습니다.

언어는 선언적 및 절차적 구문을 모두 제공합니다. 선언적으로 풍부한 사용자 인터페이스를 만든 다음 이벤트 처리 루틴과 작업을 추가할 수 있습니다.

그러나 대부분의 사용자는 좀 더 소박하게 시작해야 하며 이 기사의 목적도 그러합니다. 목표는 JavaFX 스크립트를 시작하는 방법을 보여주는 것입니다. 먼저 다음이 필요합니다.



자바 플랫폼 설정

개발자라면 물론 시스템에 JDK가 설치되어 있을 것입니다. 그러나 시스템을 한동안 업데이트하지 않은 경우에는 자바 SE 6이 설치되어 있는지 확인하십시오. 학습 곡선 일지는 JavaFX 스크립트의 컴파일러 기반 버전과 NetBeans IDE 6.1에서의 지원에 중점을 두고 있습니다. JavaFX 기술이 적용된 NetBeans IDE 6.1을 설치 및 사용하려면 시스템에 자바 SE 6의 최신 수준(현재는 자바 SE 6 업데이트 10 베타)을 설치하는 것이 좋습니다. 썬 개발자 네트워크의 자바 SE 다운로드 페이지에서 최신 JDK를 다운로드합니다. Mac OS X를 사용하는 경우에는 Apple Developer Connection의 자바 섹션에서 직접 Apple의 최신 자바 플랫폼 개발 키트(현재는 Mac OS X 10.5, 업데이트 1용 자바)를 다운로드 받을 수 있습니다.


자료 참조

새로운 환경이나 언어를 경험할 때는 교착 상태에 빠지거나 난관에 봉착하게 됩니다. 이는 최첨단 기술을 사용할 때 모두가 겪게 되는 과정입니다. 학습 곡선을 원만하게 하기 위해서는 훌륭한 문서와 예제가 매우 중요합니다. 썬 개발자 네트워크의 JavaFX 기술 허브와 함께 javafx.comProject OpenJFX 웹 사이트는 정확한 정보를 얻을 수 있는 최신 문서와 데모 자료를 제공합니다.

일 부 사용자들은 언어 참조 자료를 읽지도 않고 프로그래밍을 바로 시작하고자 할 수 있습니다. 또다른 사용자들은 JavaFX 스크립트를 실제로 사용하기 전에 모든 자료를 읽을 것입니다. 바로 시작하는 유형의 사용자더라도 일종의 언어 사양이나 자습서부터 시작해야 합니다. 전형적인 "Hello, world" 예제를 쓰기 전에 기본 언어 구문을 알아야 합니다. JavaFX 참조 페이지의 문서부터 시작하는 것이 좋습니다. 여기에서 JavaFX 스크립트 프로그래밍 언어 참조 자료 등의 참조 문서와 JavaFX 기술 시작하기NetBeans IDE를 사용하여 간단한 JavaFX 애플리케이션 생성 등의 많은 기사와 자습서로의 링크를 찾을 수 있습니다.


JavaFX 애플리케이션 생성

일부 언어 참조 문서를 읽었다면 이제는 간단한 JavaFX 애플리케이션을 만들어 볼 차례입니다. 명령줄에서 수동으로 JavaFX 애플리케이션 빌드 및 실행이 가능하긴 하지만 애플리케이션 개발을 단순화하는 많은 기능을 가진 NetBeans IDE 6.1를 사용해 봅시다. NetBeans용 JavaFX 플러그인을 설치해야 합니다.

NetBeans IDE 6.1을 설치하지 않은 경우에는 NetBeans IDE 6.1과 NetBeans용 JavaFX을 포함하는 하나의 패키지인 JavaFX 포함 NetBeans IDE 6.1 다운로드가 가능합니다. NetBeans IDE 6.1을 이미 설치한 경우에는 NetBeans 업데이트 센터에서 JavaFX 플러그인을 설치하여 JavaFX 기술 지원을 추가할 수 있습니다. NetBeans용 JavaFX는 현재 Windows 및 Mac OS/X 환경에서 사용 가능합니다. JavaFX 플러그인을 설치하면 NetBeans IDE 6.1을 사용하여 JavaFX 스크립트의 컴파일러 기반 버전으로 작성된 애플리케이션을 생성, 테스트, 디버그 및 배포할 수 있습니다. 플러그인은 JavaFX 스크립트 파일 포함을 위한 프로젝트 및 편집기 지원을 향상시킵니다. 또한 스크립트 엔진 및 라이브러리를 위한 코어 라이브러리도 제공합니다.

JavaFX 포함 NetBeans IDE 6.1이나 NetBeans용 JavaFX 플러그인을 설치했으면 첫 번째 JavaFX 애플리케이션을 빌드할 준비가 된 것입니다. 물론 "Hello, world!"부터 시작해야겠지요.

다음과 같이 프로젝트 생성을 시작합니다.

  1. 주 메뉴에서 File -> New Project를 선택합니다.
  2. New Project 마법사에서 JavaFX 범주와 JavaFX Script Application 프로젝트 유형을 선택합니다.
  3. Next 버튼을 클릭합니다.
  4. HelloWorldJFX와 같이 프로젝트의 이름을 지정합니다.
  5. 기본 프로젝트 위치를 수락하거나 다른 위치를 선택하여 이동합니다.
  6. Create Main Class 확인란을 선택된 상태로 두고 다른 기본 설정도 변경하지 않습니다.
  7. Finish 버튼을 클릭합니다.

그림 1과 같이 IDE는 지정된 프로젝트 폴더에 프로젝트 디렉토리를 생성하고 프로젝트 이름과 같은 HelloWorldJFX라는 이름을 부여합니다. HelloWorldJFX 프로젝트를 확장합니다. Source Packages 노드의 helloworldjfx 패키지 아래에 Main.fx 클래스 파일이 있습니다. IDE는 프로젝트 생성 시 Create Main Class 확인란이 선택되어 있었으므로 Main.fx 파일을 생성합니다. 이 파일에 애플리케이션의 소스 코드가 들어갑니다.


그림 1.
HelloWorldJFX 프로젝트 파일


  /*
   * Main.fx
   *
   * Created on ...
   */

  package helloworldjfx;

  /**
   * @author ...
   */

  // place your code here
 

// place your code here 라인을 다음 코드로 바꿉니다.

  import javafx.ext.swing.Label;

  Label {
      text: "Hello, world!"
  }
 


JavaFXScript 편집기는 기본 서식 설정과 코드 완성을 제공합니다. 우리와 같이 JavaFX 스크립트에 익숙하지 않은 프로그래머는 언어 구문에 확신이 들지 않을 때도 있으므로 코드 완성이 도움이 됩니다. Ctrl + Space 키를 누르면 편집기에서 코드 완성이 활성화됩니다.

또 한 JavaFX 스크립트 플러그인은 컴파일과 실행을 해 볼 필요 없이 애플리케이션의 결과를 볼 수 있는 미리보기 기능을 제공합니다. 소스 파일에 변경한 내용은 즉시 미리보기 창에 반영됩니다. 미리보기 기능은 현재 Mac OS X 플랫폼에서는 사용할 수 없습니다.

Enable Preview 버튼

을 클릭하여 미리보기 기능을 작동시킵니다. 그림 2와 같이 편집기 바로 위에서 출력을 볼 수 있습니다.



그림 2. 기본적인 "Hello, world!"

별로 놀라지 않으셨나요? 좋습니다. 설정 방법을 보여주려는 것 뿐이었지만 좀 더 재미있는 것을 해보도록 하겠습니다. JavaFX 환경은 모든 Swing UI 구성요소를 구현하므로 레이블에만 한정될 필요는 없습니다. 버튼이나 대화 상자 같은 다른 위젯을 사용할 수도 있습니다.

다음은 버튼의 이벤트 핸들러를 소개하는 예제입니다. 언어 참조 자료에서 actionfunction 구문을 읽었으면 버튼을 누를 때 메시지 상자가 표시되도록 해봅시다.


  import javafx.ext.swing.SwingFrame;
   
import javafx.ext.swing.Button;
   
import javafx.ext.swing.SwingDialog;
   
import javafx.ext.swing.Label;
 
   
SwingFrame {
       content
: Button {
           text
: "Press me!"
           action
: function() {
               
SwingDialog {
                   title
: "You pressed me"
                   content
: Label{ text: "Hey, don't do that!"}
                   visible
: true
               
}
       
}
   
}
 
   visible
: true
   
}



Main.fx 파일에 이를 입력한 후에 Press me! 버튼을 누르면 그림 3과 같은 결과가 나타납니다.

그림 3. "Press me!" 버튼 메시지


앞에서 말한 것처럼 미리보기 기능을 사용하여 코드를 컴파일 및 실행하지 않고도 애플리케이션의 결과를 볼 수 있습니다. 코드를 컴파일하려는 경우에는 Project 창에서 프로젝트를 마우스 오른쪽 버튼으로 클릭하고 Build Project를 선택합니다. 애플리케이션을 실행하려면 Project 창에서 프로젝트를 마우스 오른쪽 버튼으로 클릭하고 Run Project를 선택합니다.


구성요소 기반에서 노드 기반 UI로의 이동

이전 예제에서 Frame과 Dialog의 구성요소가 간단하게 FrameDialog가 아니라 SwingFrameSwingDialog라 는 클래스 이름을 갖는지 궁금하셨을지도 모릅니다. 그 답은 JavaFX 스크립트 개발자가 Swing 기반 구성요소의 계층 구조를 사용하는 기존 접근 방법 대신 노드 기반 접근 방법을 사용하여 UI를 구축하는 향후의 접근 방법에 관련되어 있습니다. 사실 이러한 향후의 접근 방법에 대한 초기 지원은 이미 JavaFX 라이브러리에 포함되어 있습니다. 예를 들면 javafx.application 패키지에는 노드 기반 접근 방법을 지원하는 Frame, DialogWindow 등의 클래스가 포함됩니다. 다른 접근 방법을 지원하는 클래스와의 혼동을 피하기 위해 javafx.application 패키지에 해당 항목이 있는 javafx.ext.swing 패키지는 클래스 이름에 접두어 "Swing"을 추가했습니다.

학습 곡선 시리즈에서는 계층 구조적인 Swing 기반 접근 방법을 사용했지만 javafx.ext.swing 패키지의 SwingFrame, SwingDialogSwingWindow와 같은 클래스는 임시적입니다. JavaFX 팀은 Swing 구성요소와 유사하지만 더욱 유연하고 강력한 새로운 노드 기반 구성요소 집합을 설계 중입니다.

노드 기반 접근 방법을 사용한 UI 구축에 대한 자세한 내용은 장면 그래프를 사용하여 JavaFX 스크립트에서 비주얼 개체 표시 기사를 참조하십시오. NetBeans IDE를 사용하여 간단한 JavaFX 애플리케이션 생성 자습서도 노드 기반 접근 방법을 사용하는 JavaFX 애플리케이션을 설명합니다.


프로파일

JavaFX는 특정 플랫폼이나 장치에서만 사용 가능한 클래스 그룹을 의미하는 프로파일을 지원합니다. javafx.ext.swing 패키지의 클래스는 데스크탑 프로파일에 들어 있으며 데스크탑 환경에서만 가용성이 보장됩니다. 예를 들어 많은 휴대 전화는 Swing 클래스를 갖지 않습니다. 휴대 전화와 TV를 포함한 모든 플랫폼에서 보장되는 클래스를 정의한 일반 프로파일도 있습니다. 새로운 노드 기반 구성요소는 일반 프로파일에 있으므로 모든 화면 및 장치에서 작동합니다.

JavaFX API 문서는 정확한 프로파일 사용을 보장하기 위해 하나의 프로파일에서 다른 프로파일로 전환할 수 있도록 하는 버튼을 제공합니다. 이 기사 시리즈에서는 데스크탑 환경을 위한 애플리케이션을 구축하므로 데스크탑 프로파일의 클래스와 일반 프로파일의 일부 클래스를 사용할 것입니다.


명령줄에서 JavaFX 애플리케이션 빌드 및 실행

다음과 같이 명령줄에서 JavaFX 애플리케이션을 빌드 및 실행할 수 있습니다.

  1. JavaFX Preview SDK 다운로드를 받습니다. SDK에는 JavaFX 스크립트 컴파일러, 문서, 런타임, 라이브러리 및 코드 샘플이 포함됩니다.
  2. 다운로드한 패키지를 확장합니다. 여러 디렉토리 중에 javafxcjavafx 명령을 위한 실행 가능 파일을 포함하는 bin 디렉토리가 보여야 합니다.
  3. fx 확장자를 갖는 파일(예: MyApp.fx)에 애플리케이션의 소스 코드를 저장합니다
  4. 다음과 같이 javafxc 명령을 수행하고 소스 파일을 지정하여 애플리케이션을 컴파일합니다.
       javafxc MyApp.fx

    애플리케이션을 위한 클래스 파일이 생성됩니다.

  5. 다음과 같이 javafx 명령을 수행하고 클래스 파일을 지정하여 애플리케이션을 위한 클래스 파일을 실행합니다.
       javafx MyApp

요약

새로운 기술을 조사할 때는 올바르게 시작하는 것이 중요합니다. 정확한 정보와 도구를 사용하여 시작하도록 하십시오. JavaFX 스크립트에 대한 최선의 방법은 4단계 절차를 따르는 것입니다.

  1. 최신의 Java SE Development Kit를 받습니다.
  2. 정보의 출처로 JavaFX 기술 허브, javafx.com 사이트Project OpenJFX 사이트를 사용합니다.
  3. IDE용 개발 플러그인을 받습니다. JavaFX 포함 NetBeans IDE 6.1은 새로운 JavaFX 스크립트의 컴파일러 기반 버전을 지원합니다. NetBeans IDE 6.1을 이미 설치한 경우에는 NetBeans 업데이트 센터에서 JavaFX 플러그인을 설치하여 JavaFX 기술 지원을 추가할 수 있습니다.
  4. 첫 번째 스크립트 시험에 미리보기 기능을 사용합니다.


자세한 정보

이 시리즈의 2편인 선언적 사용자 인터페이스를 참조하십시오.



이 글의 영문 원본은
Learning Curve Journal, Part 1: Exploring JavaFX Script
에서 보실 수 있습니다.

 

jxl을 통한 엑셀 저장하기

개발 이야기/Java | 2008. 1. 16. 14:08
Posted by 시반

먼저 관련사이트 에서 jexcelapi 를 다운받는다.

압축파일을 열어보면 관련 javadoc 및 소스파일도 함께 있으니 참고하시길...

여하튼 jxl.jar 파일을 관련 프로젝트에 등록한다.

 

<관련 클래스 간략설명>

jxl.write.WritableWorkbook : workbook,sheet등을 생성 및 관리하기 위한 엑셀파일관리 추상 클래스

jxl.Workbook : 기본 엑셀파일 추상 클래스

jxl.write.WritableSheet : sheet를 관리하는 인터페이스

jxl.write.WritableCellFormat : 엑셀 내 cell관련 포맷정보

jxl.write.Label : 엑셀내 필드명(엑셀의 cell에 들어있는 데이타 값이라 생각하면 된다)

jxl.write.Blank : 빈 cell관리 클래스

 

<엑셀 처리>

1. 엑셀파일을 생성한다

 WritableWorkbook testExcel = Workbook.createWorkbook(new File("sample.xls"));

 

  기존의 엑셀파일을 읽어와 처리하고자 하는 경우에는 다음과 같다.

 

 WritableWorkbook testExcel = Workbook.getWorkbook(new File("sample.xls"));

 

2. 생성된 엑셀관리 객체의 sheet를 선택한다

 WritableSheet sheet1 = testExcel.createSheet("1stShell", 0);

  위의 경우 새로이 생성된 엑셀파일내 새로운 sheet를 추가하는 것이라면

 기존의 생성된 특정 sheet를 선택하고자 하는 경우 다음과 같다

 WritableSheet sheet0 = testExcel.getSheet("preShell") ;

 

3. 셀서식을 설정한다     

WritableCellFormat titleFormat= new WritableCellFormat(); 

 - 폰트 설정

WritableCellFormat은 쉘정열 및 테두리설정 및 배경색 등 셀서식과 관련된 설정을 할 수 있다.

폰트 설정의 경우 다음과 같이 처리한다.

 

WritableCellFormat titleFormat
  = new WritableCellFormat(
           new WritableFont (WritableFont.ARIAL,              //폰트 타입.Arial 외 별다른건 없는듯 하다.
                                 20,                                          //폰트 크기
                                 WritableFont.BOLD,                  //Bold 스타일
                                 false,                                      //이탤릭체여부
                                 UnderlineStyle.NO_UNDERLINE, //밑줄 스타일
                                 Colour.WHITE,                         //폰트 색
                                 ScriptStyle.NORMAL_SCRIPT)); //스크립트 스타일

 

폰트 설정의 경우 위와 같이 Font설정 객체를 생성한후 서식객체 생성시 인자로 넣으면 된다.

다양한 생성자를 제공하고 있으니 굳이 위화면과 같이 할 필요는 없다. (API 참조)

 

-셀 서식 설정

기타 셀서식과 관련 주로 사용하는 기능을 설명하면 다음과 같다.

     titleFormat.setAlignment(Alignment.CENTRE);                     // 셀 가로정열(좌/우/가운데설정가능)
     titleFormat.setVerticalAlignment(VerticalAlignment.CENTRE); // 셀 세로정렬(상단/중단/하단설정가능)
     titleFormat.setBorder(Border.ALL, BorderLineStyle.THICK);  // 보더와 보더라인스타일 설정
     titleFormat.setBackground(Colour.ICE_BLUE);                    // 배경색 설정

4. 데이타를 셀에 등록한다

 Label title = new Label(0, 0, "테스트 타이틀",  titleFormat);  //라벨(열,행,"문장",포멧) : 숫자형은 Number를 사용
 sheet1.addCell(title);                                                // sheet1의 1열1행에 "테스트 타이틀"이라는 데이타를 넣는다

 

--> 데이타 등록을 위한 Label 생성시 첫번째 인자는 sheet의 열, 두번째 인자는 행을 의미한다는 것에 주의...

 

5. Sheet 디자인 설정(*^^*)

이부분은 해도 그만 안해도 그만이지만 깔끔한 엑셀저장을 위한 선택코스?

 

-셀 크기 변경

관련메소드는 setColumnView(몇번째 컬럼, 넓이)
   sheet1.setColumnView(0, 20); //sheet1의 첫번째 열의 크기를 20으로 설정한다

또는

  CellView cv = sheet1.getColumnView(0);

  cv.setSize(30);                    

  sheet1.setColumnView(0,cv);    //기존의 열정보 변경. 30으로 변경한다  

 

- 셀병합

   sheet1.mergeCells(0, 0, 5, 0 ); //sheet1의 1열1행의 cell을 6열1행의 셀까지 병합한다.

 

- 빈 셀 처리 

  Blank blank = new Blank(6, 0, titleFormat); // 빈 셀(열,행,포멧)

  sheet1.addCell(blank);                             // 위의 병합셀옆에 같은서식의 빈셀추가

 

6. 데이타를 파일에 저장한다. 

   testExcel.write(); // 쓰고

   testExcel.close(); // 닫자

 

서두에서 밝힌바와 같이 기타 관련 API의 내용은 압축파일내 docs 디렉토리 밑에 나와 있어여..

'개발 이야기 > Java' 카테고리의 다른 글

@Override 사용하기  (0) 2008.01.24
Generic 사용하기..*^^*  (0) 2008.01.23
JAVA API Chm파일 다운로드 링크  (0) 2007.12.21
[JBoss 보안] DataSource 패스워드 암호화  (0) 2007.06.26
[java] 예약어 enum  (0) 2007.06.04
 

JAVA API Chm파일 다운로드 링크

개발 이야기/Java | 2007. 12. 21. 13:51
Posted by 시반

chm 파일로 java api가 있는 곳입니다. 아쉽게도 한글은 아니라는거...

 

J2SE 6 documentation 도 있으니 한번 가서 받아봐두 될듯...

http://www.allimant.org/javadoc/index.php

 

J2SE 5 documentatation 은 한글이 다행히 있더군여..

(okjsp에서 링크를....)

 

6.0이 나온지 꽤 되었건만 사용해봤다기도 머한것이

기존의 패키지를 컨버젼한거 외에는

6.0에서 새로이 추가된 기능을 사용해본적이 없다는 것이 아쉽다..

 

손에 익은거만 쓰려는 이 내 귀차니즘...

 

그래서 마침 플젝도 끝났겠다..API나 훑어 보자는 맘에 함 찾아보았다...

흐음 새로운게 많네요...간만에 공부좀...*^^*

 

 

'개발 이야기 > Java' 카테고리의 다른 글

Generic 사용하기..*^^*  (0) 2008.01.23
jxl을 통한 엑셀 저장하기  (0) 2008.01.16
[JBoss 보안] DataSource 패스워드 암호화  (0) 2007.06.26
[java] 예약어 enum  (0) 2007.06.04
JAVA SE의 정규표현식  (0) 2007.05.30
 

[java] 예약어 enum

개발 이야기/Java | 2007. 6. 4. 10:08
Posted by 시반

소스를 정리하다 보니 다음과 같은 Warning이 나오는걸 확인했다.

 

'enum' should not be used as an identifier, since it is a reserved keyword from source level 5.0 on

 

흐음 대충 해석하면 enum은 1.5이상 버젼부터는 예약어로 사용하고 있으니 되도록 사용하지 말것을 권장하고 있다는 것인데...

 

검색해보니 역시 jdk1.5부터 enum 키워드가 추가되었슴을 알게 되었다.

(이궁 그럼 1.5이상으로 변경할 경우 소스 고칠게 많아 지겠군... -_-ㅋ   )

 

enum 키워드는 enumeration 이름과 괄호안으로 들어가야할 가능한 값들을 사용할때 쓰이는데 그 용법은 다음과 같다

enum Color {red, green, blue}

 

예제..


  public class EnumTest {
    public static void main(String args[]) {
      enum Color {red, green, blue};

      // Get collection of values
      System.out.println(Color.VALUES);

      // Check if collection type is java.util.List
      System.out.println(Color.VALUES instanceof java.util.List);

      // Create variable of type
      Color aColor = Color.green;

      // Use enumeration in switch
      switch(aColor) {
        case Color.red:
          System.out.println("Got red.");
          break;
        case Color.green:
          System.out.println("Got green.");
          break;
        case Color.blue:
          System.out.println("Got blue.");
          break;
      }
    }
  }

 

 

 
블로그 이미지

시반

시반(詩伴)이란 함께 시를 짓는 벗이란 뜻을 가지고 있습니다. 함께 나눌수 있는 그런 공간이길 바라며...

카테고리

분류 전체보기 (233)
개발 이야기 (73)
WEB2.0 (57)
DB2 (24)
MySQL (6)
오라클 (26)
기타 (44)
취미 (0)
잡담 (2)