接第一部分,本章將討論目前JavaFX語(yǔ)言可用的各種GUI組件并且給出一些如何使用的示例。我們會(huì)同時(shí)對(duì)比Swing的GUI組件進(jìn)行討論。
我們將分四個(gè)章節(jié)完成GUI組件的講解,本章要闡述的GUI組件如下:
在JavaFX語(yǔ)言中,邊框和布局管理器的使用同樣也是聲明性的。每個(gè)Swing/AWT布局管理器都被封裝為一個(gè) JavaFX類,該類使用特定的布局管理器實(shí)例化一個(gè)JPanel。組件通過(guò)聲明的方式使用JavaFX類提供的屬性被添加到(底部的)JPanel上。 每個(gè)Swing邊框類型也被封裝成一個(gè)屬性對(duì)應(yīng)與邊框的配置選項(xiàng)的JavaFX類。以下是一個(gè)使用EmptyBorder和GridPanel的簡(jiǎn)單示例。和您猜想的一樣,EmptyBorder對(duì)應(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
};
運(yùn)行程序顯示如下:
點(diǎn)擊按鈕三次后顯示如下:
注意:Button的action和mnemonic屬性將在后面討論...
在該示例中,通過(guò)給GridPanel的columns、rows和vgap屬性賦值,GridPanel被配置為一 列、兩行以及行間垂直間距10像素, 如果您想在列間增加間距,GridPanel還有一個(gè)hgap屬性。GridPanel的四周的被設(shè)置為30個(gè)像素大小的空邊框。
按鈕和標(biāo)簽通過(guò)將指派給cells屬性來(lái)添加到面板中。GridPanel通過(guò)在其底部的JPanel添加或刪除組件來(lái)實(shí)現(xiàn)對(duì)它的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邊框類和其對(duì)應(yīng)Swing邊框類的概述:
|
|
---|---|
JavaFX Border | Swing Border |
EmptyBorder |
EmptyBorder |
LineBorder |
LineBorder |
BevelBorder |
BevelBorder |
SoftBevelBorder |
SoftBevelBorder |
MatteBorder |
MatteBorder |
TitledBorder |
TitledBorder |
讓我們?cè)谇懊娴氖纠屑尤牒?jiǎn)單的菜單,新的代碼如下:
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
};
運(yùn)行后,按Alt+F鍵,顯示如下:
正如您所見的,菜單欄通過(guò)給窗口的menubar屬性賦值一個(gè)MenuBar類的新示例而創(chuàng)建。您通過(guò)將菜單指定給菜單欄的menus屬性來(lái)將它們添加到菜單欄中。在該示例中,只添加了一個(gè)菜單,但是任何返回Menu對(duì)象列表的表達(dá)式都可以被使用。
要定義菜單,它的的text、mnemonic和items屬性值必須被設(shè)定。
您可能已經(jīng)猜到,text屬性的類型是String,而mnemonic屬性是KeyStroke類型,它的值F是KeyStroke類的一個(gè)枚舉實(shí)例。在JavaFX中,屬性初始化屬性的靜態(tài)類型(和Java中的靜態(tài)字段情況)的枚舉值時(shí)可以不使用規(guī)范類別名直接訪問(wèn)(其他地方您必須使用F:KeyStroke替代F)。
一個(gè)菜單條目,一個(gè)text為“Exit“及其mnemonic為X的MenuItem被創(chuàng)建。它accelerator屬性同樣被賦了值。注意,在聲明中值類型名Accelerator被省略了,這是允許的。如果沒有指定類型名,將使用屬性的靜態(tài)類型,在示例中是Accelerator。此外,accelerator的modifier和keyStroke被初始化使用枚舉值。
最后,MenuItem的action屬性為function類型(例如,它是一個(gè)函數(shù),而不是一個(gè)對(duì)象),在示例中,是一行通過(guò)調(diào)用某些已經(jīng)編寫的Java代碼來(lái)直接退出應(yīng)用的操作。
JavaFX Label類支持HTML內(nèi)容。使用Label您可以使用HTML和CSS創(chuàng)建樣式文本和圖像,非常類似于典型的Web應(yīng)用。此外,通過(guò)使用JavaFX嵌入表達(dá)式,您可以在Swing應(yīng)用中象Web頁(yè)面作者使用類似JSTL或Velocity工具一樣創(chuàng)建動(dòng)態(tài)的HTML內(nèi)容。
考慮以下虛擬購(gòu)物車示例:
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
}
運(yùn)行以上程序,顯示如下:
如果您編程刪除購(gòu)物車內(nèi)容:
delete cart.items;
您將看到如下內(nèi)容:
在以上示例中,內(nèi)嵌的JavaFX表達(dá)式(粗體顯示)動(dòng)態(tài)創(chuàng)建HTML表格列和表格單元的內(nèi)容。當(dāng)這些表達(dá)式依賴的對(duì)象有變化時(shí),Label的HTML內(nèi)容將自動(dòng)更新。
以上示例還非常有趣,因?yàn)槠溲菔玖耸褂帽磉_(dá)式定義屬性值的用法。Item類的totalCost屬性和Cart類的 subTotal屬性被綁定為表達(dá)式以計(jì)算它們的值。任何時(shí)候這些表達(dá)式的依賴對(duì)象發(fā)生變化,屬性值將被自動(dòng)重新計(jì)算并更新??紤]在電子表格中,某些單元 格包含指向其他單元格的表達(dá)式,當(dāng)您在這些其他單元格輸入數(shù)據(jù),包含依賴它們的表達(dá)式的單元格值也被自動(dòng)更新了。
HTML中的圖像
JavaFX Label類實(shí)際上封裝了一個(gè)特殊的JEditPane,該JEditorPane使用一個(gè)支持用Java類轉(zhuǎn)載器從JAR文件中載入圖像的共享圖像緩存。因此,您可以就像普通的文件URL一樣使用HTML的<img>元素引用您的應(yīng)用的圖像資源包。
超鏈接
Label類同樣支持HTML超鏈接,內(nèi)嵌一個(gè)特殊的URL給HTML<a>元素的href屬性。
這樣的URL使用JavaFX #操作符創(chuàng)建,該操作符生成一個(gè)字符串化對(duì)象引用(Stringified Object Reference)指向后續(xù)可以被JavaFX復(fù)引用的操作對(duì)象。?操作符,例如:
var a = 20;
var b = #a;
assert b instanceof String; // 通過(guò)
var c = (Number) ?b;
assert a == c; // 通過(guò)
Label類的HTML顯示器認(rèn)識(shí)諸如HTML的<a href=url>這樣的URL,使用URL來(lái)響應(yīng)元素的鼠標(biāo)點(diǎn)擊,并且如果URL值指向一個(gè)函數(shù)或操作的話,它可以調(diào)用該函數(shù)或操作。
例如,以下是使用帶超鏈接標(biāo)簽代替按鈕的前面按鈕點(diǎn)擊示例的重寫版本:
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
};
以上示例中粗體的表達(dá)式創(chuàng)建一個(gè)新的遞增model的numClicks屬性的操作。使用#操作符生成后續(xù)將被鍵入到HTML標(biāo)記中的指向該操作的URL。
運(yùn)行該程序,顯示如下:
點(diǎn)擊超鏈接兩次后,顯示如下:
未完,待續(xù)...
出自:http://blog.eshangrao.com/index.php/2007/05/20/392-javafxjavafx-script-with-eclipse