2014年1月28日 星期二

JavaFX Chart

圖表 (Chart) 常運用於試算表如Microsoft Excel、Mac Numbers、Apache OpenOffice Calc等辦公室軟體,透過圖表讓資料以更簡單明瞭的方式呈現。Java Swing並沒有提供圖表的類別,因此若需使用圖表,只能自行開發或使用Third-Party軟體廠商所提供的API套件。此外,圖表亦常與商業智慧 (Business Intelligence) 搭配,透過商業智慧軟體與資料庫或資料倉儲整合,提供向下分析與互動功能的動態圖表,根據指標在特定期間的變化,以動態的方式呈現資訊,使圖表產生更多樣化的呈現,常見的商業智慧軟體有SAP BusinessObjects、SAS Business Intelligence、Oracle Business Intelligence、IBM Cognos、MicroStrategy等,下圖為商業智慧之示範:
有鑑於圖表的重要性,因此JavaFX內建圖表,包括圓形圖、區域圖、長條圖、折線圖、散佈圖、泡泡圖、堆疊區域圖與堆疊長條圖等,分別由以下類別建立:
  • 圓形圖:javafx.scene.chart.PieChart類別。
  • 區域圖:javafx.scene.chart.AreaChart類別。
  • 長條圖:javafx.scene.chart.BarChart類別。
  • 泡泡圖:javafx.scene.chart.BubbleChart類別。
  • 折線圖:javafx.scene.chart.LineChart類別。
  • 散佈圖:javafx.scene.chart.ScatterChart類別。
  • 堆疊區域圖:javafx.scene.chart.StackedAreaChart類別。
  • 堆疊長條圖:javafx.scene.chart.StackedBarChart類別。
除了PieChart類別之外,其餘類別皆繼承自XYChart抽象類別,主要原因是此類型的圖表皆以XY座標軸 (橫軸與縱軸) 描述資料,由於皆繼承自XYChart抽象類別,因此其處理方式均十分類似。

PieChart類別與繼承自XYChart抽象類別的圖表類別之最大差別在於,前者僅以PieChart.Data類別設定各扇形區域的資料,而後者則是先以XYChart.Series類別設定各數列,再以XYChart.Data類別設定各數列的資料,因此可允許多個數列資料在同一圖表中。

此外,PieChart類別與XYChart抽象類別繼承自Chart抽象類別,為JavaFX圖表的基礎類別。Chart抽象類別分別定義以下的屬性值:
  • animated:當資料改變時,是否以動態的方式顯示圖表。
  • legend:圖表圖例 (Legend)。
  • legendSide:圖表圖例的置放位置。
  • legendVisible:是否顯示圖表圖例。
  • title:圖表標題 (Title)。
  • titleSide:圖表標題的置放位置。
為描述XY座標軸的類型,分別由CategoryAxisNumberAxis類別以文字與數值做為座標軸的資料:
  • 類別座標軸:javafx.scene.chart.CategoryAxis類別。
  • 數值座標軸:javafx.scene.chart.NumberAxis類別。
除了上述類別之外,JavaFX並提供各類別對應的Builder類別,透過Builder類別可精簡程式長度:
  • 圓形圖:javafx.scene.chart.PieChartBuilder類別。
  • 區域圖:javafx.scene.chart.AreaChartBuilder類別。
  • 長條圖:javafx.scene.chart.BarChartBuilder類別。
  • 泡泡圖:javafx.scene.chart.BubbleChartBuilder類別。
  • 折線圖:javafx.scene.chart.LineChartBuilder類別。
  • 散佈圖:javafx.scene.chart.ScatterChartBuilder類別。
  • 堆疊區域圖:javafx.scene.chart.StackedAreaChartBuilder類別。
  • 堆疊長條圖:javafx.scene.chart.StackedBarChartBuilder類別。
圓形圖 (Pie Chart) 又稱為圓餅圖,圓形圖將圖表劃分成幾個不同比例的扇形區域 (Slice),藉以描述量、頻率或百分比之間的相對關係,在圓形圖中,每個扇形區域的面積大小代表數量的比例,由於圓形圖以面積取代長度表達相對關係,反而加大了對各數據比較的難度,因此若需要進行數據比較,建議使用折線圖或長條圖。下圖為圓形圖之示範
區域圖 (Area Chart) 用以強調一段時間的變動程度,例如可使用區域圖繪製代表一段時間內利潤的資料,強調利潤總和。區域圖也可藉由顯示繪製值的總和,顯示部分與整體的關係。下圖為區域圖向下分析示範
向下分析 (Drill-Down Analysis) 是商業智慧一個特殊的功能,將資料或數個圖表建立主從 (Master-Detail) 關聯,當點選主要圖表資料時,則顯示其對應的次要圖表資料。

長條圖 (Bar Chart) 用以顯示一段時間內資料的變更或比較不同項目間的差異,長條圖又可分為水平長條圖與垂直長條圖。但與區域圖不同的是,長條圖須同時以CategoryAxisNumberAxis類別設定座標軸的類型,若以CategoryAxis設定水平座標軸 (則為類別)、NumberAxis設定垂直座標軸 (則為數值),則為垂直長條圖;反之,若以NumberAxis設定水平座標軸 (則為數值)、CategoryAxis設定垂直座標軸 (則為類別),則為水平長條圖,在開發長條圖時須特別注意。下圖為長條圖向下分析示範
折線圖 (Line Chart) 用以顯示一段時間內的連續資料,且根據一般的比例進行設定,因此適合顯示相等間隔內資料的趨勢,在折線圖中,類別資料沿著水平座標軸均勻分散,所有資料沿著垂直座標軸均勻分散。下圖為折線圖向下分析示範
散佈圖 (Scatter Chart) 與折線圖十分類似,同樣用以顯示一段時間內的連續資料,且根據一般的比例進行設定,因此適合顯示相等間隔內資料的趨勢。兩者的差別在於,在散佈圖中,其水平與垂直座標軸均為數值資料,水平與垂直的交會為單一座標點,座標點依據資料會平均或不平均的分佈在散佈圖上。下圖為散佈示範
泡泡圖 (Bubble Chart) 為散佈圖的變化,泡泡圖常用以顯示財務資料,座標點以泡泡呈現,不同的泡泡大小用以強調數值的大小。與散佈圖不同的是,為處理泡泡的大小,因此需以XYChart.Data類別分別設定X座標軸資料、Y座標軸資料與泡泡的大小。下圖為泡泡示範
堆疊區域圖 (Stacked Area Chart) 類似於區域圖,不同的是,堆疊區域圖在資料數列上堆疊兩個以上的資料數列,而且Y座標軸資料為個類別資料的加總。下圖為堆疊區域向下分析示範
堆疊長條圖 (Stacked Bar Chart) 類似於長條圖,不同的是,堆疊長條圖在資料數列上堆疊兩個以上的資料數列。下圖為堆疊長條向下分析示範
除了以類別處理之外,亦可使用CSS設定圖表樣式,其中較特殊的是長條圖,可使用圖像代替原有的長條樣式:
參考資料】

[1] 黃嘉輝,深入研究JavaFX 2。
[2] 黃嘉輝,深入研究Java Swing。
[5] JavaFX 2.2 API Specification.
[6] Java Platform, Standard Edition 7 API Specification.

© Chia-Hui Huang

JavaFX Flow Pane

Flow Pane

Flow Pane的類別為javafx.scene.layout.FlowPane,類似於Java AWT的Flow Layout。

Flow Pane依其配置方向 (Orientation),分為水平與垂直兩種方式,如同其名稱Flow (流動) 一般

以水平方向為例,Flow Pane將物件依序由左至右、由上至下配置,當物件配置超過容器寬度,則超過一列 (Row) 時,會依序自下一列開始配置。

以垂直方向為例,Flow Pane將物件依序由上至下、由左至右配置,當物件配置超過容器高度,則超過一行 (Column) 時,會依序自下一行開始配置。其預設配置方向為水平方向。

FlowPane類別的建構函式為:

  public FlowPane()
  public FlowPane(Orientation orientation)
  public FlowPane(double hgap, double vgap)
  public FlowPane(Orientation orientation, double hgap, double vgap)

其中參數hgapvgap分別設定物件間的水平垂直間距,單位為像素。參數orientation設定Flow Pane的配置方向,為以下的常數值:
  • Orientation.HORIZONTAL:水平方向。
  • Orientation.VERTICAL:垂直方向。
請參考以下範例,示範如何以Flow Pane配置按鈕物件,首先以setHgap()setVgap()方法分別設定Flow Pane中物件間的水平與垂直間距為5單位像素,接著以add()方法將按鈕物件加至Flow Pane之中,Flow Pane會將物件以預設的方式由左至右依序配置,當物件超過一列之配置時,會依序自下一列開始配置。


// 設定Button物件
Button button1 = new Button("OK");
Button button2 = new Button("Cancel");
Button button3 = new Button("Yes");
Button button4 = new Button("No");

// 設定FlowPane
FlowPane flowpane = new FlowPane();
// 設定FlowPane中物件間的水平間距
flowpane.setHgap(5);
// 設定FlowPane中物件間的垂直間距
flowpane.setVgap(5);

// 將Button物件加至FlowPane之中
flowpane.getChildren().add(button1);
flowpane.getChildren().add(button2);
flowpane.getChildren().add(button3);
flowpane.getChildren().add(button4);
...


【執行結果】

除了FlowPane類別之外,JavaFX並提供FlowPaneBuilder類別配置物件,與FlowPane類別一樣,FlowPaneBuilder類別依其配置方向,分為水平與垂直兩種方式,其預設配置方向為水平方向。以FlowPaneBuilder類別配置物件的程式架構如下,首先以create()方法建立FlowPaneBuilder的實體 (Instance),最後再以build()方法以FlowPaneBuilder物件建立Flow Pane的實體,其間以alignment()hgap()vgap()orientation()等方法分別設定物件的水平與垂直對齊方式、物件間的水平與垂直間距、配置方向等,再以children()方法將物件置於Flow Pane區域中:


FlowPane flowpane = FlowPaneBuilder.create()
  .alignment(...)
  .hgap(...)
  .vgap(...)
  .orientation(...)
  .children(...)
  .build()


請參考以下範例。


// 設定ImageView物件
ImageView images[] = new ImageView[9];

for (int i=0; i<9; i++) {
  // 讀取Java Archive檔案內的圖像檔案
  images[i] = new ImageView(new Image(
    FlowPaneDemo.class.getResourceAsStream(
    "images/Icon0"+i+".png")));
}

// 建立SceneBuilder的實體(Instance)
Scene scene = SceneBuilder.create()
  .width(220)
  .height(220)
  .root(
    // 建立FlowPaneBuilder的實體(Instance)
    FlowPaneBuilder.create()
      .alignment(Pos.CENTER)
      .hgap(5)
      .vgap(5)
      .orientation(Orientation.VERTICAL)
      .padding(new Insets(5, 0, 5, 0))
      .children(images)
      .build()
  )
  .build();

...


參考資料】

[1] 黃嘉輝,深入研究JavaFX 2。
[2] 黃嘉輝,深入研究Java Swing。
[5] JavaFX 2.2 API Specification.
[6] Java Platform, Standard Edition 7 API Specification.

© Chia-Hui Huang

2014年1月27日 星期一

JavaFX FreeCell

新接龍(FreeCell)是一個典型的撲克牌遊戲,最早可追溯至1945年由斯堪納維亞人(Scandinavian)所創的遊戲,稱為Napoleon in St. Helena。1960年代由C. L. Baker所設計的撲克牌遊戲,俗稱Baker's Game,可謂新接龍的最早雛型。此外,在Microsoft Windows作業系統中另有接龍與連環新接龍遊戲(Klondike、Solitaire、Patience)。

遊戲的玩法與策略如下:
  • 遊戲首先將52張撲克牌分別置於8個直行,其中4個直行有7張撲克牌,其餘4個直行則有6張撲克牌,每張撲克牌皆正面朝上。另外尚有4個暫存區與4個收牌區,分別在左右兩側。遊戲之目的是將所有撲克牌依順序由A到K且相同花色一疊移至收牌區。
  • 將撲克牌移至某一直行時,其順序必須由大到小且需不同的花色間隔排列。
  • 將撲克牌移至收牌區時,必須以相同花色,依順序由A到K移動。
  • 某直行最上面的撲克牌可移至暫存區、另一直行最上面或收牌區等位置,但需依規則2與3移動。
  • 暫存區中的撲克牌可移至某直行的最上面或收牌區等位置,但需依規則2與3移動。
此次以JavaFX 2設計FreeCell,並以Microsoft Windows的FreeCell為範本。


Example: Link

© Chia-Hui Huang

Google雲端硬碟

Google雲端硬碟 (Google Drive) 是Google於2012年4月24日提供的一項線上同步儲存服務,原名Google Docs雲端文件,初期提供線上建立文件、試算表、簡報、繪圖、表單等功能,之後Google將Google Docs雲端文件整合至Google雲端硬碟之中。Google雲端硬碟提供類似Dropbox的雲端目錄管理,在Google Drive中稱為Folder Location,可同步上傳個人電腦中的檔案至Google雲端硬碟之中。

Google雲端硬碟提供以下之功能:
  • 線上建立文件:線上建立文件可執行所有編輯文件的基本操作,包括變更字型、建立表格、插入公式、插入圖片、項目符號清單、按欄位排序等功能。除了線上建立文件之外,亦可上載現有的文件檔案,並轉換成Google雲端檔案格式,Google雲端硬碟支援如DOC、DOCX、XLS、XLSX、PPT、PPTX、CSV、RTF、ODT、ODS等常見的檔案格式。
  • 即時共用與合作:可自由選擇存取文件的使用者,只要輸入欲共用文件使用者的電子郵件,並傳送邀請則完成共用,被邀請進行編輯或檢視的使用者只要登入Google,則可馬上存取共用的文件、試算表或簡報。此外,並提供與其他使用者即時進行編輯及簡報的功能,可讓多人同時檢視與進行編輯,共用的文件、試算表或簡報會出現在交談視窗中,文件修訂版本並顯示進行變更的使用者、內容與時間,每個加入共用簡報的使用者都能夠自動跟隨簡報者的步調檢視簡報。
  • 安全儲存與組織文件:Google雲端硬碟提供自動儲存功能,不必擔心硬碟當機或電力中斷等問題。此外,無需下載任何檔案,則可從任何設有網路連線和標準瀏覽器存取文件、試算表或簡報,並可將文件、試算表和簡報以DOC、DOCX、XLS、XLSX、PPT、PPTX、CSV、ODS、ODT、PDF、RTF和HTML等格式儲存或匯出副本至電腦上。
  • 支援離線功能:Google雲端硬碟提供離線功能,在沒有網際網路的情況之下,仍可檢視與編輯Google文件,離線功能除支援一般的桌上型電腦之外,並支援Apple iOS與Android的平板電腦和智慧型手機。
  • 支援平板電腦與智慧型手機:Google雲端硬碟除了支援一般電腦之外,並支援Apple iOS與Android的平板電腦與智慧型手機,可讓使用者隨時透過行動裝置取得Google雲端硬碟的相關文件。
Google雲端硬碟的檔案大小限制分別如下:
  • 文件:上限為1,024,000個字元,上載的文件檔案經轉換成Google文件格式之後,其檔案大小不能超過2 MB。
  • 試算表:上限為40萬個儲存格,每張工作表最多為256欄,上載的試算表檔案經轉換成Google試算表格式之後,其檔案大小不能超過20 MB,每張工作表的儲存格上限為40萬個及256欄。
  • 簡報:上限為50 MB,相當於200張投影片,上載的簡報檔案經轉換成Google簡報格式之後,其檔案大小不能超過50 MB。
  • 其他:目前系統不支援大型檔案,所上載的檔案全部總計可佔用5 GB空間。
欲使用Google雲端硬碟,首先需註冊Google帳號,此帳號可自https://accounts.google.com申請,Google網站採單一帳號登入方式,一經登入則可使用Google所提供的雲端服務,如Gmail、Google雲端硬碟、Google協作平台、Google+、Google Play、Google網上論壇、Blogger等,如下圖所示。


待登入Google之後,在Google首頁的上方會顯示雲端服務選單,如下圖所示。


點選「雲端硬碟」選項,則可進入Google雲端硬碟。


Google雲端硬碟的首頁分成兩部份,左側為導覽面板,中間為瀏覽文件清單,茲分別說明如下。

導覽面板

導覽面板類似於Microsoft Windows檔案總管或Mac OS X Finder,用以瀏覽檔案、文件、資料夾等,分別包括以下項目:
  • 我的雲端硬碟:顯示使用者在Google雲端硬碟中建立、同步處理或上傳的所有檔案、文件、自訂資料夾等,並可設定將「我的雲端硬碟」與電腦的「Google雲端硬碟資料夾」同步。點選「我的雲端硬碟」或自訂資料夾,則會於中間的瀏覽文件清單畫面中顯示所有檔案與資料夾,包括標題、擁有者與上次修改日期等。
  • 與我共用:顯示其他使用者所共用的檔案、文件與資料夾,依最後修改日期排序,並列出其他使用者最後一次儲存項目的時間、檔案或資料夾的擁有者,若所共用的檔案尚未查閱,則將以粗體顯示。欲同步處理「與我共用」中的檔案,可將檔案移至「我的雲端硬碟」中進行同步。「與我共用」中的檔案並不包含以郵寄共用的檔案、設為「擁有連結的使用者」或「公開」的檔案。
  • 星號標記:僅顯示標註星號的項目。
  • 活動:顯示最近編輯的所有檔案,包括所建立、共用或曾以網址連結開啟的所有項目,以此查看即時更新及瞭解與其他使用者所修改的內容。
  • 離線:顯示離線的項目,其中檔案與資料夾的名稱之後會附加「離線項目」。
  • 所有項目:顯示所有的項目,包括首頁中隱藏的項目,但不包括「垃圾桶」中的項目。
  • 垃圾桶:顯示已刪除的項目。
瀏覽文件清單 

瀏覽文件清單位於Google雲端硬碟的中間部份,用以瀏覽檔案、文件與資料夾,可使用右上方的「排序依據」選項,依上次編輯的項目、上次修改時間、上次開啟的項目、標題及配額使用量等選項排序。瀏覽文件清單提供兩種顯示模式,分別為清單與格狀模式,其切換按鈕位於畫面右上方。


點選左側的清單按鈕,文件會以清單的方式顯示文件的詳細資料,包括標題、擁有者與上次修改日期等資訊


點選右側的格狀按鈕,文件則以格狀方式,依序由左至右、由上而下顯示檔案、文件與資料夾,此外,若為Google雲端文件、Google雲端試算表、Google雲端簡報或PDF格式等檔案,則會以預覽的方式顯示



【參考資料】

[1] 雲端硬碟線上說明:https://support.google.com/drive/?hl=zh_TW。 
[2] 黃嘉輝,工作就該如此有效率!Google雲端應用軟體,上奇科技,July 2013。 

© Chia-Hui Huang

JavaFX Anchor Pane

Anchor Pane

Anchor Pane的類別為javafx.scene.layout.AnchorPane,類似於Java Swing的Spring Layout。

Java Swing的Spring Layout定義物件間其水平或垂直邊緣(Edge)間的距離,以此距離及物件的長寬定義各物件的位置。

Anchor Pane則如同其名稱Anchor(錨)一般,含有定位之意,並以下列方法設定Anchor Pane各區域與物件間之距離:
  • setTopAnchor():設定Anchor Pane區域上方與物件上方之距離。
  • setBottomAnchor():設定Anchor Pane區域下方與物件下方之距離。
  • setLeftAnchor():設定Anchor Pane區域左方與物件左方之距離。
  • setRightAnchor():設定Anchor Pane區域右方與物件右方之距離。
此距離依序稱為topAnchor、bottomAnchor、leftAnchor與rightAnchor,藉此將物件定位於上、下、左、右四個區域之中,不論視窗或Java Applet的大小如何改變,其所配置的物件均定位於所指定的區域中,不會改變其位置。

為說明上述方法與定位間之關係,請參考下圖之示範。
以物件1為例,分別以setTopAnchor()setLeftAnchor()方法設定Anchor Pane區域上方與物件上方之距離(topAnchor)及區域左方與物件左方之距離(leftAnchor),因此物件1將會定位於左上方之區域中。

以物件2為例,分別以setBottomAnchor()setRightAnchor()方法設定Anchor Pane區域下方與物件下方之距離(bottomAnchor)及區域右方與物件右方之距離(rightAnchor),因此物件2將會定位於右下方之區域中。

請參考以下範例:


// 設定Button物件
Button button1 = new Button("Top-Left");
button1.setPrefSize(100,20);
Button button2 = new Button("Bottom-Left");
button2.setPrefSize(100,20);
Button button3 = new Button("Top-Right");
button3.setPrefSize(100,20);
Button button4 = new Button("Bottom-Right");
button4.setPrefSize(100,20);

// 設定AnchorPane
AnchorPane anchorpane = new AnchorPane();

// 設定Anchor Pane區域上方與Button物件上方之距離
anchorpane.setTopAnchor(button1, 10.0);
// 設定Anchor Pane區域左方與Button物件左方之距離
anchorpane.setLeftAnchor(button1, 10.0);

// 設定Anchor Pane區域下方與Button物件下方之距離
anchorpane.setBottomAnchor(button2, 10.0);
// 設定Anchor Pane區域左方與Button物件左方之距離
anchorpane.setLeftAnchor(button2, 10.0);

// 設定Anchor Pane區域上方與Button物件上方之距離
anchorpane.setTopAnchor(button3, 10.0);
// 設定Anchor Pane區域右方與Button物件右方之距離
anchorpane.setRightAnchor(button3, 10.0);

// 設定Anchor Pane區域下方與Button物件下方之距離
anchorpane.setBottomAnchor(button4, 10.0);
// 設定Anchor Pane區域右方與Button物件右方之距離
anchorpane.setRightAnchor(button4, 10.0);

// 將所有Button物件加至AnchorPane之中
anchorpane.getChildren().addAll(button1, button2, button3, button4);
...


【執行結果】
除了AnchorPane類別之外,JavaFX並提供AnchorPaneBuilder類別配置物件,AnchorPaneBuilder類別配置物件的程式架構如下,首先以create()方法建立AnchorPaneBuilder的實體 (Instance),中間以children()方法將物件置於Anchor Pane區域中,最後再以build()方法以AnchorPaneBuilder物件建立Anchor Pane的實體:


AnchorPane anchorpane = AnchorPaneBuilder.create()
  .children(...)
  .build();


請參考以下範例:


/ 以AnchorPaneBuilder建立AnchorPane
AnchorPane anchorpane = AnchorPaneBuilder.create()
  .children(button1, button2, button3, button4)
  .build();

// 設定Anchor Pane區域上方與Button物件上方之距離
anchorpane.setTopAnchor(button1, 10.0);
// 設定Anchor Pane區域左方與Button物件左方之距離
anchorpane.setLeftAnchor(button1, 10.0);

// 設定Anchor Pane區域下方與Button物件下方之距離
anchorpane.setBottomAnchor(button2, 10.0);
// 設定Anchor Pane區域左方與Button物件左方之距離
anchorpane.setLeftAnchor(button2, 10.0);

// 設定Anchor Pane區域上方與Button物件上方之距離
anchorpane.setTopAnchor(button3, 10.0);
// 設定Anchor Pane區域右方與Button物件右方之距離
anchorpane.setRightAnchor(button3, 10.0);

// 設定Anchor Pane區域下方與Button物件下方之距離
anchorpane.setBottomAnchor(button4, 10.0);
// 設定Anchor Pane區域右方與Button物件右方之距離
anchorpane.setRightAnchor(button4, 10.0);
...


參考資料】

[1] 黃嘉輝,深入研究JavaFX 2。
[2] 黃嘉輝,深入研究Java Swing。
[5] JavaFX 2.2 API Specification.
[6] Java Platform, Standard Edition 7 API Specification.

© Chia-Hui Huang

2014年1月25日 星期六

JavaFX Border Pane

一般應用程式在處理物件配置的方式上,通常是以絕對座標定義其物件位置,以Microsoft Visual Basic為例,由於不需考慮跨平臺的差異性,因此各物件通常是以絕對座標定義其物件位置。由於Java需考慮各作業系統在定義座標系統的差異以及跨平臺的考量,因此在處理物件位置上,是以相對位置的方式處理,在Java AWT與Java Swing中稱為Layout Manager (配置管理員),而在JavaFX則稱為Layout Pane (配置窗格或配置面板)。

Java AWT與Java Swing分別提供以下之Layout Manager類別:
  • java.awt.BorderLayout
  • java.awt.CardLayout
  • java.awt.FlowLayout
  • java.awt.GridBagLayout
  • java.awt.GridLayout
  • javax.swing.BoxLayout
  • javax.swing.GroupLayout
  • javax.swing.OverlayLayout
  • javax.swing.SpringLayout
JavaFX類似於Java AWT與Java Swing,提供以下之Layout Pane類別,均繼承自javafx.scene.layout.Pane類別:
  • javafx.scene.layout.AnchorPane
  • javafx.scene.layout.BorderPane
  • javafx.scene.layout.FlowPane
  • javafx.scene.layout.GridPane
  • javafx.scene.layout.HBox
  • javafx.scene.layout.StackPane
  • javafx.scene.layout.TilePane
  • javafx.scene.layout.VBox
JavaFX與Java Swing最大的不同在於,JavaFX提供Layout Pane Builder,透過Builder類別可精簡程式,以下為Layout Pane Builder之相關類別:
  • javafx.scene.layout.AnchorPaneBuilder
  • javafx.scene.layout.BorderPaneBuilder
  • javafx.scene.layout.FlowPaneBuilder
  • javafx.scene.layout.GridPaneBuilder
  • javafx.scene.layout.HBoxBuilder
  • javafx.scene.layout.StackPaneBuilder
  • javafx.scene.layout.TilePaneBuilder
  • javafx.scene.layout.VBoxBuilder
Border Pane

Border Pane的類別為javafx.scene.layout.BorderPane,類似於Java AWT的Border Layout。

如同其名稱Border (邊界) 一般,Java AWT的Border Layout將容器分為東、南、西、北及中央五個區域,而JavaFX的Border Pane則將容器分為上、下、左、右及中央五個區域,每一區域只能置放一個物件,雖然名稱不同,但其相對位置是一樣的

JavaFX的Border Pane則是以下列「方法」將物件置於Border Pane的上、下、左、右及中央五個區域之中:
  • setTop()
  • setBottom()
  • setLeft()
  • setRight()
  • setCenter()
此外,Java AWT的Border Layout所配置的物件大小會因視窗或Java Applet大小的改變而有所變更,但JavaFX的Border Pane,則不論視窗或Java Applet的大小如何改變,其所配置的物件大小均維持不變。

請參考以下範例


// 設定Button物件
Button button1 = new Button("Top");
Button button2 = new Button("Bottom");
Button button3 = new Button("Left");
Button button4 = new Button("Right");
Button button5 = new Button("Center");

// 設定BorderPane
BorderPane borderpane = new BorderPane();

// 將Button物件置於BorderPane的上方區域
borderpane.setTop(button1);
// 將Button物件置於BorderPane的下方區域
borderpane.setBottom(button2);
// 將Button物件置於BorderPane的左方區域
borderpane.setLeft(button3);
// 將Button物件置於BorderPane的右方區域
borderpane.setRight(button4);
// 將Button物件置於BorderPane的中央區域
borderpane.setCenter(button5);

// 設定BorderPane的對齊方式為水平與垂直方向均靠中央對齊
borderpane.setAlignment(button1, Pos.CENTER);
borderpane.setAlignment(button2, Pos.CENTER);
borderpane.setAlignment(button3, Pos.CENTER);
borderpane.setAlignment(button4, Pos.CENTER);
borderpane.setAlignment(button5, Pos.CENTER);

// 設定Scene的Layout Pane為BorderPane
Scene scene = new Scene(borderpane);
// 設定Stage的標題
primaryStage.setTitle("Border Pane Demo");
// 設定Stage的寬度
primaryStage.setWidth(250);
// 設定Stage的高度
primaryStage.setHeight(250);
primaryStage.setScene(scene);
primaryStage.setResizable(true);

// 顯示Stage
primaryStage.show();
...


【執行結果】

除了BorderPane類別之外,JavaFX並提供BorderPaneBuilder類別配置物件,以BorderPaneBuilder配置物件的程式架構如下,首先以create()方法建立BorderPaneBuilder的實體 (Instance),最後再以build()方法以BorderPaneBuilder物件建立Border Pane的實體,其間以top(), bottom(), left(), right(), center()等方法將物件置於Border Pane各區域中,各方法可為任意順序或省略:

BorderPane borderpane = BorderPaneBuilder.create()
  .top(...)
  .bottom(...)
  .left(...)
  .right(...)
  .center(...)
  .build();


請參考以下範例

// 設定ImageView物件
ImageView images[] = new ImageView[5];

for (int i=0; i<5; i++) {

  // 讀取Java Archive檔案內的圖像檔案
  images[i] = new ImageView(new Image(
    BorderPaneDemo.class.getResourceAsStream(
    "images/Icon0"+i+".png")));
}

// 建立SceneBuilder的實體 (Instance)

Scene scene = SceneBuilder.create()
  .width(250)
  .height(250)
  .root(
    // 建立BorderPaneBuilder的實體 (Instance)
    BorderPaneBuilder.create()
      // 將ImageView物件置於BorderPane各區域中
      .top(images[0])
      .bottom(images[1])
      .left(images[2])
      .right(images[3])
      .center(images[4])
      // 以BorderPaneBuilder物件建立Border Pane的實體 (Instance)
      .build()
  )
  .build();

// 設定Stage的標題

primaryStage.setTitle("Border Pane Demo");

primaryStage.setScene(scene);

primaryStage.setResizable(true);

// 顯示Stage

primaryStage.show();
...


【執行結果】

【參考資料】

[1] 黃嘉輝,深入研究JavaFX 2。
[2] 黃嘉輝,深入研究Java Swing。
[5] JavaFX 2.2 API Specification.
[6] Java Platform, Standard Edition 7 API Specification.

© Chia-Hui Huang

2014年1月24日 星期五

JavaFX與SWT

除了Java Swing之外,JavaFX亦可與SWT (Standard Widget Toolkit) 互通,SWT最初是由IBM開發的一套類似於Java AWT與Java Swing的API套件,現已整合至Eclipse開發環境之中。

JavaFX與SWT彼此之間透過javafx.embed.swt.FXCanvas類別所建立的JavaFX Canvas處理,以便在SWT程式中使用JavaFX類別,FXCanvas類別繼承自SWT的Canvas類別,因此JavaFX Canvas可視為畫布 (Canvas) ,用以配置JavaFX物件。

以下範例示範在以SWT中以FXCanvas類別建立JavaFX Canvas並配置JavaFX物件,其中以Button類別建立圖像按鈕:


// JavaFX API
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.Scene;

import javafx.embed.swt.FXCanvas;
import javafx.scene.control.Button;
import javafx.scene.control.ContentDisplay;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Group;

// SWT API
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.RowLayout;

/**
 *
 * @author Leo Huang
 */
public class SWTDemo {

  public static void main(String[] args) {
    final org.eclipse.swt.widgets.Display display =
      new org.eclipse.swt.widgets.Display();
    final org.eclipse.swt.widgets.Shell shell =
      new org.eclipse.swt.widgets.Shell(display);
    final org.eclipse.swt.layout.RowLayout layout =
      new org.eclipse.swt.layout.RowLayout();
    shell.setLayout(layout);
   
    // Create SWT button
    final org.eclipse.swt.widgets.Button swtButton =
      new org.eclipse.swt.widgets.Button(shell, SWT.PUSH);
    swtButton.setText("SWT Button");
    swtButton.addListener(SWT.Selection, new Listener() {
      public void handleEvent(Event event) {
        swtButton.setText("SWT Event");
        shell.layout();
      }
    });

    // Create FXCanvas
    final FXCanvas fxCanvas = new FXCanvas(shell, SWT.NONE) {
      public Point computeSize(int wHint, int hHint, boolean changed) {
        getScene().getWindow().sizeToScene();
        int width = (int) getScene().getWidth();
        int height = (int) getScene().getHeight();
        return new Point(width, height);
      }
    };

    // Create JavaFX button
    final Button jfxButton = new Button();
    jfxButton.setText("JavaFX Button");
    jfxButton.setGraphic(new ImageView(new Image(
      SWTDemo.class.getResourceAsStream("images/dukeswing.gif"))));
    jfxButton.setContentDisplay(ContentDisplay.TOP);
    jfxButton.setPrefWidth(100);
    jfxButton.setOnAction(new EventHandler<ActionEvent>() {
      public void handle(ActionEvent event) {
        jfxButton.setText("JavaFX Event");
        shell.layout();
      }
    });

    Group root = new Group();
    root.getChildren().add(jfxButton);
    Scene scene = new Scene(root);
    fxCanvas.setScene(scene);
   
    shell.pack();
    shell.setSize(200, 200);
    shell.open();

    while (!shell.isDisposed()) {
      if (!display.readAndDispatch()) {
        display.sleep();
      }
    }
    display.dispose(); 
  }
} 


【執行結果】

【參考資料】

[1] 黃嘉輝,深入研究JavaFX 2。
[2] 黃嘉輝,深入研究Java Swing。
[5] JavaFX 2.2 API Specification.
[6] Java Platform, Standard Edition 7 API Specification.

© Chia-Hui Huang