2014년 9월 16일 화요일

JavaFX UI - 16.Hyperlink


Hyperlink 클래스는 Labeled 컨트롤의 또 한 가지 유형이다.

기본 hyperlink 구현에서는 아래와 같은 세 가지의 상태를 가진다.



1. Creating a Hyperlink

다음
예제 코드는 hyperlink를 생성하는 예시이다.

Example 16-1 Typical Hyperlink



Hyperlink 클래스의 setText 메서드는 하이퍼링크의 텍스트를 지정한다. Hyperlink 클래스는 Labeled 클래스를 상속받았으므로 하이퍼링크 텍스트의 폰트나 색상을 따로 지정할 수 있다. setOnAction 메서드는 하이퍼링크가 클릭되었을 때 취할 액션을 지정할 수 있다.


2. Linking the Local Content

아래
화면은 하이퍼링크를 통해 로컬 디렉토리로부터의 이미지를 화면에 그리는 샘플 어플리케이션이다.
 




다음 예제는 위 어플리케이션에 대한 소스 코드이다.

Example 16-2 Using Hyperlinks to View Images





사용자가 하이퍼링크를 클릭하면 하이퍼링크의 상태가 visited 상태로 변한다. Hyperlink 클래스의 setVisited 메서드를 사용하여 하이퍼링크의 상태를 변경할 수 있다. 위 예제에서 ‘Refresh links’ 버튼을 클릭하면 모든 하이퍼링크의 상태가 unvisited 상태로 바뀔 것이다.


3. Linking the Remote Content

WebView
브라우저 컨트롤을 사용하면, JavaFX 어플리케이션에서 HTML 컨텐트를 디스플레이할 수 있다. WebView 컨트롤은 기본 웹 페이지 브라우징 기능을 제공한다. 즉, 웹페이지를 보여주고 link를 통한 페이지 이동과 java script 실행 등과 같은 사용자 상호작용을 지원한다.

다음 예제는 이미지와 텍스트를 모두 가진 Hyperlink 컨트롤을 이용하여, 원격 웹 페이지들을 보여주는 어플리케이션 소스 코드이다.

Example 16-3 Loading Remote Web Pages




 

위 코드를 실행하면 아래와 같은 어플리케이션 모습을 볼 수 있다.
 

JavaFX UI - 15.Progress Bar & Progress Indicator


ProgressIndicator 클래스와 ProgressIndicator의 서브 클래스인 ProgressBar 클래스는 작업이 진행 중임을 표현하기 위한 컨트롤로써, 현재 작업이 얼마만큼 진행되었는지를 알려준다.

ProgressBar는 막대 형태로 표현되는데 반해, ProgressIndicator 클래스는 파이 차트 형태로 보여진다.




1. Creating Progress Controls

아래
와 같은 코드를 통해 progress 컨트롤을 생성할 수 있다.

Example 15-1 Implementing the Progress Bar and Progress Indicator



작업이 끝나는 시점을 판별하기 어려운 상황이 종종 있는데, 이를 위해 progress 컨트롤을 indeterminate 모드로 만들 수 있다.

아래 화면은 상황에 따른 progress 컨트롤의 모습을 보여준다.



아래 예제는 위 화면에서 보여지는 어플리케이션에 대한 소스 코드이다.


Example 15-2 Enabling Different States of Progress Controls



0에서 1 사이의 progress 값은 진행률을 나타낸다. 예를 들어 0.4는 40%의 진행률을 의미한다. Progress 값이 음수이면 progress 컨트롤이 indeterminate 모드에 있음을 의미한다. Progress 컨트롤이 indeterminate 모드에 있는지를 체크하기 위햐여 isIndeterminate 메서드를 사용할 수 있다.


2. Indicating Progress in Your User Interface

아래
예제는 슬라이더의 값에 따라 progress 컨트롤들의 값을 조정하는 어플리케이션의 소스 코드이다.

Example 15-3 Receiving the Progress Value from a Slider




위 예제를 실행하면 아래와 같은 화면이 나타난다.
 


JavaFX UI - 14.Slider


Slider 컨트롤은 track과 draggable thumb로 구성된다. 또한 슬라이딩 범위의 수치 값들을 나타내기 위해 tick mark와 tick label들도 포함한다.

아래 그림은 전형적인 slider의 모습을 보여준다.




1. Creating a Slider

아래
예제 코드는 위 그림과 같은 slider를 생성하는 코드 샘플이다.

Example 14-1 Creating a Slider


setMinsetMax 메서드는 슬라이딩 범위의 최소 및 최대 값을 지정하기 위해 사용한다. setValue 메서드는 slider의 현재 값을 지정하기 위해 사용되며, 값이 지정되면 thumb의 위치도 그 값에 따라 이동한다.

setShowTickMarkssetShowTickLabels 메서드는 slider에 tick mark나 tick label을 보여줄지 여부를 지정한다. setMajorTickUnit은 slider의 major tick mark 간의 단위 간격을 지정하고, setMinorTickCount는 major tick 사이의 minor tick의 개수를 지정한다.
또한 setSnapToTicks 메서드를 이용하여 슬라이더의 현재 값이 항상 tick mark에 위치하도록 할 수 있다.

setBlockIncrement 메서드는 사용자가 트랙 상의 임의 위치를 클릭할 때, thumb가 이동하는 단위거리를 지정한다.


2. Using Sliders in Graphical Applications

아래
어플리케이션 화면은, 사진의 렌더링 속성을 조정하기 위하여 세 개의 슬라이더를 사용한다. 각 슬라이더는 각각 다른 비쥬얼 특성을 조절한다. (opacity level, sepia tone value, scaling factor)




아래 예제는 위와 같은 어플리케이션에 대한 소스 코드이다.

Example 14-2 Slider Sample


 

ImageView 객체의 opacity 프로퍼티가 첫 번째 슬라이더의 값에 따라 변경되고, SepiaTone 효과의 레벨이 두 번째 슬라이더 값에 따라 조정된다. 마지막 슬라이더는 ImageView의 setScaleXsetScaleY 메서드를 이용하여 사진의 스케일을 조정한다.

JavaFX UI - 13.Separator


Separator 클래스는 UI 엘리먼트들을 수평 또는 수직으로 분할하여 구분하기 위한 분리자 컨트롤로써, 어떠한 액션을 유발하지는 않는다. 디폴트로 separator는 수평 방향을 가지며, setOrientation 메서드를 통해 방향을 변경할 수 있다.


1. Creating a Separator

래 예제는 하나의 수평 separator와 하나의 수직 separator를 생성한다.

Example 13-1 Vertical and Horizontal Separators



Separator 클래스는 Node 클래스를 상속하고 있으므로, Node 클래스의 모든 멤버 변수들을 가지고 있다.

일반적으로, separator는 UI 컨트롤들의 그룹을 나누기 위해 사용된다. 아래 예제는 체크박스들을 분리시키기 위해 separator가 사용되는 코드이다.

Example 13-2 Using a Separator Between Checkbox Categories


 
위 예제 코드가 어플리케이션에 추가되면 아래와 같은 UI가 보여진다.



2. Adding Separators to the UI of Your Application

Separator
는 UI를 구성하기 위해 사용될 수 있다. 아래 화면은 일기예보 정보를 디스플레이하는 어플리케이션 화면이다.



위 화면에서 Sepatator는 Label과 ImageView 객체들을 분할하여 화면을 구성하기 위해 사용되었다.

Example 13-3 Using Separators in a Weather Forecast Application

 
 

위 예제는 수평, 수직 separator를 모두 사용하였고, GridPane 컨테이너의 열과 행 공간을 확장하여 separator를 배치하였다.


3. Styling Separators

Example
13-3의 모든 separator들에 대해 동일한 스타일을 적용하려면, 이를 정의하는 CSS 파일을 하나 생성하여 어플리케이션 main 클래스와 동일한 패키지에 저장한다.

아래 스타일 정의는 separator에 대한 예시이다.

Example 13-4 Using CSS Classes to Style Separators

 
위와 같이 정의된 CSS를 어플리케이션에 적용하기 위해서는 Scene 클래스의 getStylesheets 메서드를 사용한다.

Example 13-5 Enabling Style Sheets in a JavaFX Application



아래 화면은 위 스타일이 적용된 후의 모습이다.
 

2014년 9월 15일 월요일

JavaFX UI - 12.Combo Box


Combo box는 사용자들이 여러 옵션 중 하나를 선택할 수 있도록 해주는 UI 컨트롤이다.
Choice box와 달리, Combo box는 포함하고 있는 항목들이 일정 개수를 넘어가더라도 스크롤 형태로 보여주므로 유용하다.



1. Creating Combo Boxes

Combo box를 생성하기 위해서는 ComboBox 클래스 인스턴스를 만들고, 그곳에 들어갈 아이템들을 observable list 형태로 만들어 정의해야 한다. 이는 ChoiceBox, ListView, TableView와 같은 UI 컨트롤들과 동일한 방식이다.

Example 12-1 Creating a Combo Box with an Observable List
 


위와 같이 정의된 컴보박스가 화면에 보여지는 모습은 아래와 같다.
 



콤보박스가 생성된 이후, 언제라도 새로운 아이템들을 추가할 수 있다. 다음 예제는 컴보박스에 세개의 아이템들을 추가하는 코드이다.

Example 12-2 Adding Items to a Combo Box


ComboBox 클래스는 몇 가지 편리한 프로퍼티 및 메서드들을 제공한다.

  • setValue - 콤보박스 내 항목들 중 하나를 선택한다. setValue 메서드가 호출되면 해당 콤보박스의 selectionModel 프로퍼티의 ‘선택 아이템’ 값이 setValue 메서드를 통해 ‘선택된 값’으로 변경된다. 이는 설사 지정한 값이 콤보박스 내 항목에 없을지라도 마찬가지다.
  • getValue - 컴보박스에서 현재 선택된 아이템 값을 반환한다.
  • setVisibleRowCount - 콤보박스의 드롭다운 리스트에서 한번에 보일 row 수를 지정한다.

ComboBox 클래스가 어떠한 타입의 아이템이라도 받아들일 수 있도록 정의되어 있기는 하지만, Node 타입 또는 Node를 상속한 타입의 객체는 사용하지 않도록 한다. 이는 combo box의 디폴트 cell factory에서 Node 아이템들을 직접 셀에 올리는 것으로 인해 콤보박스의 드롭다운 버튼까지 덮어버리기 때문이다.

또한 Scene graph 상에의 모든 Node 들은 여러 위치에 동시에 위치할 수 없다는 제약이 있는데, 이로 인해 콤보박스 상에서 선택된 Node 아이템은 콤보박스 리스트로부터 제거된다. 콤보박스에서 선택 값으로 보여야 할 Node 객체가 콤보박스 리스트에서도 동시에 보일 수 없기 때문이다. 이러한 상황에서 콤보박스의 선택 아이템이 바뀔 경우 이전에 선택된 Node 아이템은 콤보박스 리스트로 반환되고 새로 선택된 Node 아이템은 콤보박스 리스트에서 제거된다.

아래 예제는 콤보박스로 UI를 구성하는 예를 보여준다.

Example 12-3 Creating Combo Boxes and Adding Them to the Scene
 


위 예제를 실행한 결과는 아래 화면과 같다.
 




2. Editable Combo Boxes

일반적으로 email 클라이언트 어플리케이션들은 ‘받는사람’을 지정할 때, 목록에서 선택하는 것과 직접 입력하는 것을 모두 지원한다. ComboBox 클래스의 setEditable(true) 메서드를 호출함으로써 콤보박스가 편집 가능하도록 만들 수 있다. 또한 setPromptText 메서드를 통해, 어떤 아이템도 선택되지 않은 콤보박스에 대해 표시할 prompt 메시지를 지정할 수도 있다.


Example 12-4 Processing Newly Typed Values in an Editable Combo Box




3. Applying Cell Factories to Combo Boxes

콤보박스가
디폴트로 가지는 외관이나 동작방식을 커스터마이징 하기 위하여 cell factory 메커니즘을 사용할 수 있다.

아래 예제는 이전 예제에서의 priority 콤보박스에 대해 cell factory 메커니즘을 적용한 코드이다

Example 12-5 Implementing a Cell Factory for the Priority Combo Box


 

위 예제에서 콤보박스에 지정된 cell factory는 콤보 아이템을 디스플레이하기 위해 사용될 ListCell 객체를 생성한다. 여기서 사용된 ListCell은 커스터마이징되었으며, 콤보 아이템의 너비를 지정하기 위해 setPrefWidth 메서드를 사용하였고 priority에 따라 텍스트 색상이 변경되도록 하였다.

아래 화면은 위 예제를 실행했을 때의 화면이다.

JavaFX UI - 11.Table View


Table 생성을 위해 가장 중요한 클래스들은 TableView, TableColumn, TableCell 이다. Table에 데이터를 채우기 위해서는 data model을 구현하고 cell factory를 구현해야 한다.

Table 클래스들은 컬럼 데이터를 정렬하거나 필요시 컬럼 크기를 재조정하는 built-in 기능들을 제공한다.

아래 화면은 e-mail 주소 정보를 담고 있는 전형적인 table 형태를 보여준다.

 



1. Creating a Table

아래
예제는 세 개의 컬럼을 가지는 빈 테이블을 생성한다.

Example 11-1 Adding a Table



위 예제를 실행한 결과 화면은 아래와 같다.
 




setVisible 메서드를 통해 컬럼의 visibility를 조정할 수 있다.

표현하고자 하는 데이터 구조가 복잡한 경우, nested column을 구성할 수 있다. 예를 들어 두 개의 e-mail 계정을 포함하는 컬럼을 만들고 싶은 경우, 두 개의 서브 컬럼을 만든 후 다른 메인 컬럼에 추가할 수 있다.

Example 11-2 Creating Nested Columns




위의 코드라인을 Example 11-1에 추가하면, 다음과 같은 결과를 확인할 수 있다.
 

 

위 화면에서 table에 데이터가 정의되지 않았기 때문에 “No content in table”이라는 표준 메시지가 보여진다. 이 때, setPlaceholder 라는 메서드를 통해 이 표준 메시지 대신 보여줄 다른 Node 객체를 지정할 수 있다.


2. Defining the Data Model

JavaFX
어플리케이션에서 table을 생성할 때, data model을 정의하는 클래스를 구현하는 것이 좋다. 아래 예제에서는 Person이라는 data model 클래스를 생성한다.

Example 11-3 Creating the Person Class


firstName, lastName, email 이라는 string property들을 생성하고 이들 각각에 대한 get, set 메서드를 제공한다.
Person 클래스를 통해 data model이 정의되었다면, ObservableList를 생성하여 table에 넣을 레코드들을 정의할 수 있다. 아래 예제는 이 과정을 보여준다.

Example 11-4 Defining Table Data in an Observable List


다음은 위에서 정의한 데이터와 table column들을 서로 연결시켜주어야 한다.
 

Example 11-5 Setting Data Properties to Columns




setCellValueFactory 메서드는 각 컬럼에 대해 값을 얻을 수 있는 Callback 인터페이스를 등록한다. 예제에서 나오는 PropertyValueFactory 클래스는 Callback 인터페이스를 구현하고 있으며 각 컬럼에 대한 cell value factory로 사용되고 있다. PropertyValueFactory의 생성자에는 컬럼명이 파라미터로 주어지는데, call 메서드가 호출되면 이 컬럼명에 해당하는 컬럼 값을 반환한다.

Data model에 기반하는 데이터들이 만들어지고, data model과 table의 컬럼 간의 관계가 정의되면, TableView 클래스의 setITems 메서드를 사용하여 준비된 데이터를 테이블에 추가할 수 있다.

TableView에 추가되는 데이터들은 ObservableList를 통해 관리되는데, ObservableList 내의 엘리먼트들에 변경이 발생하게되면 TableView의 내용이 자동으로 갱신된다.

Example 11-6 Creating a Table and Adding Data to It
 




위 예제를 실행한 결과 화면은 아래와 같다.

 



3. Adding New Rows

이전
예시 화면에 나오는 테이블은 다섯 개의 row들을 포함하고 있다.

이 테이블 상의 각 컬럼들에 대하여 새로운 값을 입력하기 위해 text field를 사용할 수 있다. TextField 컨트롤은 사용자로부터 텍스트 값을 입력 받을 수 있도록 해준다. 아래 코드는 각 컬럼에 대한 텍스트 값을 입력받기 위한 세 개의 text field를 생성하였고, 데이터를 추가할 수 있는 버튼을 생성하였다.

Example 11-7 Using Text Fields to Enter New Items in the Table




아래 예제는 테이블에 레코드를 추가할 수 있는 전체 코드이다.

Example 11-8 Table with the Text Fields to Enter New Items


 
 
 




위 예제를 실행하면 아래와 같은 화면을 볼 수 있다.
 




4. Sorting Data in Columns

TableView
클래스는 컬럼 데이터를 정렬할 수 있는 built-in 기능을 제공한다. 사용자가 테이블 상의 컬럼 헤더를 클릭하면 해당 컬럼 값을 기준으로 레코드가 정렬된다. 첫 번째 클릭은 오름차순으로, 두 번째 클릭은 내림차순으로 정렬이 이루어지고 세 번째 클릭은 정렬 옵션이 제거된다. 초기 디폴트로는 어떠한 정렬도 적용되지 않는다.

사용자는 테이블 내의 여러 컬럼들에 대해 정렬할 수 있다. 이 때 각 컬럼들에 대한 정렬 우선순위가 주어져야 한다. 여러 컬럼들에 대해 정렬하기 위해서는 shift 키를 누른 상태에서 정렬하고자 하는 순서대로 컬럼의 헤더를 클릭한다.

아래 화면은 first name에 대해 오름차순으로, last name에 대해 내림차순으로 정렬한 테이블 모습이다.
 


개발자들이 TableColumn 클래스의 setSortType 메서드를 통해 어플리케이션 코드 내에서 컬럼의 정렬을 정의할 수도 있다. 예를 들면 다음과 같은 코드 라인을 통해 emailCol 컬럼을 내림차순으로 정렬할 수 있다.
emailCol.setSortType(TableColumn.SortType.DESCENDING);

컬럼 기반 정렬을 하기 위한 또 다른 방법은 TableView 객체에 정의된 sortOrder라는 observable list에 TableColumn 인스턴스를 추가하거나 제거하는 것이다. 이 list에 들어있는 컬럼의 순서가 정렬 우선순위가 된다.
정렬을 막기 위해서는 TableColumn 클래스의 setSortable(false) 메서드를 호출하면 된다.


5. Editing Data in the Table

TableView
클래스는 테이블 형식의 데이터를 화면에 표현할 뿐만 아니라, 편집할 수 있는 기능도 제공한다. 테이블 컨텐츠를 편집하기 위해서는 setEditable 메서드를 사용한다.

TableColumn의 setCellFactory 메서드는 그 컬럼에 해당하는 테이블 셀을 제공해 줄 cell factory (실제로는 Callback 인터페이스 구현체)를 지정한다. 아래 예제에서는 셀의 편집을 위해 TextField가 테이블 셀로 사용되도록 구현하였다. setOnEditCommit 메서드는 편집 완료에 대한 이벤트 핸들러를 등록하기 위해 사용되며, 편집을 처리하고 변경된 값을 해당 테이블 셀에 반영하는 작업이 이 이벤트 핸들러에서 이루어진다.

Example 11-9 Implementing Cell Editing




어플리케이션의 완벽한 코드는 아래와 같다.


Example 11-10 TableViewSample with Enabled Cell Editing


 
 
 
 
 



아래 화면은 위 예제를 실행시켰을 때의 모습을 보여준다. 테이블 셀을 편집하기 위해서는 셀 안에 새로운 값을 입력하고 엔터 키를 누른다. 엔터 키가 눌리기 전까지는 셀이 편집되지 않는다.




TextField 컨트롤의 기본 구현에서는 편집이 완료되기 위해 사용자가 반드시 엔터 키를 눌러야한다. 그러나 focus의 이동 시에 편집이 완료되도록 하기 위해 TextField를 재정의할 수 있다.

Example 11-11 Alternative Solution Of Cell Editing


 
 
 
 
 
 
 


6. Adding Maps of Data to the Table

JavaFX
SDK 2.2부터, Map 데이터가 테이블에 추가될 수 있으며, MapValueFactory 클래스를 통해 Map 데이터를 테이블에 표출할 수 있다.

Example 11-12 Adding Map Data to the Table


 



MapValueFactory 클래스는 Callback 인터페이스를 구현한 것으로, setCellValueFactory 메서드를 통해 TableColumn 인스턴스에 할당되어 그 컬럼에 해당하는 셀의 값을 결정하기 위해 사용된다.

generateDataInMap 메서드에서의 dataRow hash map은 하나의 레코드를 의미하는데, 이 map은 두 개의 string 키(Column1MapKey, Column2MapKey)를 사용하여 두 컬럼 값을 저장한다. 즉, TableView에 추가되는 데이터는 Map 객체들의 리스트이며, 각 Map 객체는 하나의 레코드를 나타내며 키 값을 통해 구분되는 컬럼 값들을 포함하고 있다. MapValueFactory 클래스는 Map 객체로부터 특정 컬럼의 값을 얻어 반환하는 Callable 구현체이다.

위 예제를 실행하면 아래와 같은 결과 화면을 볼 수 있다.