接第一部分,本章將討論目前JavaFX語言可用的各種GUI組件并且給出一些如何使用的示例。我們會同時對比Swing的GUI組件進行討論。
我們將分四個章節(jié)完成GUI組件的講解,本章要闡述的GUI組件如下:
在JavaFX語言中,邊框和布局管理器的使用同樣也是聲明性的。每個Swing/AWT布局管理器都被封裝為一個 JavaFX類,該類使用特定的布局管理器實例化一個JPanel。組件通過聲明的方式使用JavaFX類提供的屬性被添加到(底部的)JPanel上。 每個Swing邊框類型也被封裝成一個屬性對應(yīng)與邊框的配置選項的JavaFX類。以下是一個使用EmptyBorder和GridPanel的簡單示例。和您猜想的一樣,EmptyBorder對應(yīng)于javax.swing.border.EmptyBorder,而GridPanel與java.awt.GridLayout一致。
import javafx.ui.*;
class ButtonClickModel {
attribute numClicks: Number;
}
var model = new ButtonClickModel();
var win = Frame {
width: 300
height:200
content: GridPanel {
border: EmptyBorder {
top: 30
left: 30
bottom: 30
right: 30
}
rows: 2
columns: 1
vgap: 10
cells:
[Button {
text: "I'm a button!"
mnemonic: I
action: operation() {
model.numClicks++;
}
},
Label {
text: bind "Number of button clicks: {model.numClicks}"
}]
}
visible: true
};
運行程序顯示如下:
點擊按鈕三次后顯示如下:
注意:Button的action和mnemonic屬性將在后面討論...
在該示例中,通過給GridPanel的columns、rows和vgap屬性賦值,GridPanel被配置為一 列、兩行以及行間垂直間距10像素, 如果您想在列間增加間距,GridPanel還有一個hgap屬性。GridPanel的四周的被設(shè)置為30個像素大小的空邊框。
按鈕和標簽通過將指派給cells屬性來添加到面板中。GridPanel通過在其底部的JPanel添加或刪除組件來實現(xiàn)對它的cells屬性的插入或刪除。
JavaFX支持的其他布局管理器原理與此類似,以下表格是這些布局管理器的概述:
|
|
---|---|
JavaFX Widget | Layout Manager |
GridPanel |
GridLayout |
GridBagPanel |
GridBagLayout |
FlowPanel |
FlowLayout |
BorderPanel |
BorderLayout |
Box |
BoxLayout |
StackPanel |
Romain Guy's StackLayout |
CardPanel |
CardLayout |
GroupPanel |
org.jdesktop.layout.GroupLayout |
下面是JavaFX邊框類和其對應(yīng)Swing邊框類的概述:
|
|
---|---|
JavaFX Border | Swing Border |
EmptyBorder |
EmptyBorder |
LineBorder |
LineBorder |
BevelBorder |
BevelBorder |
SoftBevelBorder |
SoftBevelBorder |
MatteBorder |
MatteBorder |
TitledBorder |
TitledBorder |
讓我們在前面的示例中加入簡單的菜單,新的代碼如下:
import javafx.ui.*;
import java.lang.System;
class ButtonClickModel {
attribute numClicks: Number;
}
var model = new ButtonClickModel();
var win = Frame {
width: 300
height:200
menubar: MenuBar {
menus: Menu {
text: "File"
mnemonic: F
items: MenuItem {
text: "Exit"
mnemonic: X
accelerator: {
modifier: ALT
keyStroke: F4
}
action: operation() {
System.exit(0);
}
}
}
}
content: GridPanel {
border: EmptyBorder {
top: 30
left: 30
bottom: 30
right: 30
}
rows: 2
columns: 1
vgap: 10
cells:
[Button {
text: "I'm a button!"
mnemonic: I
action: operation() {
model.numClicks++;
}
},
Label {
text: bind "Number of button clicks: {model.numClicks}"
}]
}
visible: true
};
運行后,按Alt+F鍵,顯示如下:
正如您所見的,菜單欄通過給窗口的menubar屬性賦值一個MenuBar類的新示例而創(chuàng)建。您通過將菜單指定給菜單欄的menus屬性來將它們添加到菜單欄中。在該示例中,只添加了一個菜單,但是任何返回Menu對象列表的表達式都可以被使用。
要定義菜單,它的的text、mnemonic和items屬性值必須被設(shè)定。
您可能已經(jīng)猜到,text屬性的類型是String,而mnemonic屬性是KeyStroke類型,它的值F是KeyStroke類的一個枚舉實例。在JavaFX中,屬性初始化屬性的靜態(tài)類型(和Java中的靜態(tài)字段情況)的枚舉值時可以不使用規(guī)范類別名直接訪問(其他地方您必須使用F:KeyStroke替代F)。
一個菜單條目,一個text為“Exit“及其mnemonic為X的MenuItem被創(chuàng)建。它accelerator屬性同樣被賦了值。注意,在聲明中值類型名Accelerator被省略了,這是允許的。如果沒有指定類型名,將使用屬性的靜態(tài)類型,在示例中是Accelerator。此外,accelerator的modifier和keyStroke被初始化使用枚舉值。
最后,MenuItem的action屬性為function類型(例如,它是一個函數(shù),而不是一個對象),在示例中,是一行通過調(diào)用某些已經(jīng)編寫的Java代碼來直接退出應(yīng)用的操作。
JavaFX Label類支持HTML內(nèi)容。使用Label您可以使用HTML和CSS創(chuàng)建樣式文本和圖像,非常類似于典型的Web應(yīng)用。此外,通過使用JavaFX嵌入表達式,您可以在Swing應(yīng)用中象Web頁面作者使用類似JSTL或Velocity工具一樣創(chuàng)建動態(tài)的HTML內(nèi)容。
考慮以下虛擬購物車示例:
import javafx.ui.*;
class Item {
attribute id: String;
attribute productId: String;
attribute description: String;
attribute inStock: Boolean;
attribute quantity: Number;
attribute listPrice: Number;
attribute totalCost: Number;
}
attribute Item.totalCost = bind quantity*listPrice;
class Cart {
attribute items: Item*;
attribute subTotal: Number;
}
operation sumItems(itemList:Item*) {
var result = 0.00;
for (item in itemList) {
result += item.totalCost;
}
return result;
}
attribute Cart.subTotal = bind sumItems(items);
var cart = Cart {
items:
[Item {
id: "UGLY"
productId: "D100"
description: "BullDog"
inStock: true
quantity: 1
listPrice: 97.50
},
Item {
id: "BITES"
productId: "D101"
description: "Pit Bull"
inStock: true
quantity: 1
listPrice: 127.50
}]
};
Frame {
content: Label {
text: bind
"<html>
<h2 align='center'>Shopping Cart</h2>
<table align='center' border='0' bgcolor='#008800' cellspacing='2' cellpadding='5'>
<tr bgcolor='#cccccc'>
<td><b>Item ID</b></td>
<td><b>Product ID</b></td>
<td><b>Description</b></td>
<td><b>In Stock?</b></td>
<td><b>Quantity</b></td>
<td><b>List Price</b></td>
<td><b>Total Cost</b></td>
<td> </td>
</tr>
{
if (sizeof cart.items == 0)
then "<tr bgcolor='#FFFF88'><td colspan='8'><b>Your cart is empty.</b></td></tr>"
else foreach (item in cart.items)
"<tr bgcolor='#FFFF88'>
<td>{item.id}</td>
<td>{item.productId}</td>
<td>{item.description}</td>
<td>{if item.inStock then "Yes" else "No"}</td>
<td>{item.quantity}</td>
<td align='right'>{item.listPrice}</td>
<td align='right'>{item.totalCost}</td>
<td> </td>
</tr>"
}
<tr bgcolor='#FFFF88'>
<td colspan='7' align='right'>
<b>Sub Total: ${cart.subTotal}</b>
</td>
<td> </td>
</tr>
</table>
</html>"
}
visible: true
}
運行以上程序,顯示如下:
如果您編程刪除購物車內(nèi)容:
delete cart.items;
您將看到如下內(nèi)容:
在以上示例中,內(nèi)嵌的JavaFX表達式(粗體顯示)動態(tài)創(chuàng)建HTML表格列和表格單元的內(nèi)容。當這些表達式依賴的對象有變化時,Label的HTML內(nèi)容將自動更新。
以上示例還非常有趣,因為其演示了使用表達式定義屬性值的用法。Item類的totalCost屬性和Cart類的 subTotal屬性被綁定為表達式以計算它們的值。任何時候這些表達式的依賴對象發(fā)生變化,屬性值將被自動重新計算并更新。考慮在電子表格中,某些單元 格包含指向其他單元格的表達式,當您在這些其他單元格輸入數(shù)據(jù),包含依賴它們的表達式的單元格值也被自動更新了。
HTML中的圖像
JavaFX Label類實際上封裝了一個特殊的JEditPane,該JEditorPane使用一個支持用Java類轉(zhuǎn)載器從JAR文件中載入圖像的共享圖像緩存。因此,您可以就像普通的文件URL一樣使用HTML的<img>元素引用您的應(yīng)用的圖像資源包。
超鏈接
Label類同樣支持HTML超鏈接,內(nèi)嵌一個特殊的URL給HTML<a>元素的href屬性。
這樣的URL使用JavaFX #操作符創(chuàng)建,該操作符生成一個字符串化對象引用(Stringified Object Reference)指向后續(xù)可以被JavaFX復(fù)引用的操作對象。?操作符,例如:
var a = 20;
var b = #a;
assert b instanceof String; // 通過
var c = (Number) ?b;
assert a == c; // 通過
Label類的HTML顯示器認識諸如HTML的<a href=url>這樣的URL,使用URL來響應(yīng)元素的鼠標點擊,并且如果URL值指向一個函數(shù)或操作的話,它可以調(diào)用該函數(shù)或操作。
例如,以下是使用帶超鏈接標簽代替按鈕的前面按鈕點擊示例的重寫版本:
import javafx.ui.*;
import java.lang.System;
class ButtonClickModel {
attribute numClicks: Number;
}
var model = new ButtonClickModel();
var win = Frame {
width: 300
height:200
menubar: MenuBar {
menus: Menu {
text: "File"
mnemonic: F
items: MenuItem {
text: "Exit"
mnemonic: X
accelerator: {
modifier: ALT
keyStroke: F4
}
action: operation() {
System.exit(0);
}
}
}
}
content: GridPanel {
border: EmptyBorder {
top: 30
left: 30
bottom: 30
right: 30
}
rows: 2
columns: 1
vgap: 10
cells:
[Label {
text: bind
"<html>
<a href='{#(operation() {model.numClicks++;})}'>
I'm a hyperlink!
</a>
</html>"
},
Label {
text: bind "Number of button clicks: {model.numClicks}"
}]
}
visible: true
};
以上示例中粗體的表達式創(chuàng)建一個新的遞增model的numClicks屬性的操作。使用#操作符生成后續(xù)將被鍵入到HTML標記中的指向該操作的URL。
運行該程序,顯示如下:
點擊超鏈接兩次后,顯示如下:
未完,待續(xù)...
出自:http://blog.eshangrao.com/index.php/2007/05/20/392-javafxjavafx-script-with-eclipse