發(fā)布于:2021-01-30 10:05:20
0
56
0
GroovyFX是一個使編寫javafx2.x應用程序更加簡單和自然的庫。GroovyFX利用Groovy的Builder模式的強大功能,使開發(fā)人員能夠以簡潔的聲明式風格進行編寫。以這種方式構造ui的能力使得可視化正在構建的用戶界面變得更容易。簡短易懂的代碼也易于維護和擴展。GroovyFX完全支持JavaFX的所有高級特性,如控件、布局、圖形、動畫、聲音、視頻、圖表等等。
GroovyFX的0.2版本可以作為Sonatype的Maven存儲庫的快照提供。其組ID為網址:org.codehaus.groovyfx它的工件ID就是groovyfx。在本文中,我將使用最新版本:0.2-SNAPSHOT。
在撰寫本文時,Oracle的JavaFX團隊正在完成JavaFX2.1的工作。我預計這一版本將在本文發(fā)布后不久發(fā)布,因此本文中的所有代碼示例都將使用groovyfx0.2-SNAPSHOT,它是GroovyFX的版本,跟蹤javafx2.1中的更改。
我最近發(fā)表了一篇博客文章,詳細介紹了如何在Gradle項目和帶有@Grab注釋的Groovy腳本中使用GroovyFX?;蛘?,您可以直接從GitHub克隆項目,并按照項目的GitHub頁面上的說明進行構建(確保您正在使用develop分支)。
構建場景
JavaFX用戶界面是通過構建場景圖來創(chuàng)建的。因此,GroovyFX有一個SceneGraphBuilder類,它包裝了javafxapi類,并使用Groovy的生成器語法使它們可用。但是,很少直接實例化和使用SceneGraphBuilder對象。相反,您通常會使用GroovyFX類的靜態(tài)start方法,向它傳遞一個執(zhí)行GroovyFX代碼的閉包。清單1所示的示例說明了這一點,它顯示了一個基本的GroovyFX“Hello,World”程序。
清單1:Hello World
import groovyx.javafx.GroovyFX
GroovyFX.start {
stage(title: "GroovyFX Hello World", visible: true) {
scene(fill: black, width: 530, height: 300) {
hbox(padding: 80) {
text(text: "Groovy", style: "-fx-font-size: 80pt") {
fill linearGradient(endX: 0, stops: [palegreen, seagreen])
}
text(text: "FX", style: "-fx-font-size: 80pt") {
fill linearGradient(endX: 0, stops: [cyan, dodgerblue])
effect dropShadow(color: dodgerblue, radius: 25, spread: 0.25)
}
}
}
}
}
JavaFX中的主要應用程序容器是stage。當作為桌面應用程序運行時,它對應于應用程序的窗口;當作為瀏覽器中的小程序運行時,它對應于應用程序的內容區(qū)域。stage包含一個場景,該場景保留對場景圖根節(jié)點的引用,該節(jié)點是一個數據結構,定義了應用程序顯示的內容。因此,每個JavaFX應用程序都由一個Stage、一個場景和一個或多個場景圖節(jié)點類組成。在清單1所示的GroovyFX代碼中很容易找到這種結構,其中場景圖的根是JavaFX Hbox類的一個實例。HBox是一個布局節(jié)點,它以水平線排列其子節(jié)點。清單1顯示了根HBox節(jié)點有兩個子文本節(jié)點,它們并排顯示字符串“Groovy”和“FX”,如圖1所示。
細心的讀者無疑已經推斷出GroovyFX中使用的命名模式。groovyfxbuilder語法中的節(jié)點與其對應的JavaFX類具有相同的名稱,類名的第一個大寫字母轉換為小寫。因此javafxstage類在GroovyFX中被稱為Stage。類似地,LinearGradient變?yōu)長inearGradient,HBox變?yōu)镠Box,Button變?yōu)锽utton,依此類推。
這些類的屬性可以通過將屬性名稱用作映射中的鍵來設置,映射作為參數傳遞給生成器節(jié)點。下面的代碼創(chuàng)建了一個stage,其title屬性設置為“GroovyFX Hello World”。
GroovyFX還提供了一些方便的快捷方式來聲明場景圖節(jié)點和屬性。請注意清單1中的linearGradient聲明。GroovyFX允許您使用快捷方式,例如按名稱引用顏色,而不是使用靜態(tài)值,例如“顏色:青色”. 此外,您可以簡單地傳遞一個顏色數組作為lineargradent的stops屬性,GroovyFX將使用這些顏色自動創(chuàng)建等間距的漸變停止。這些方便的快捷方式使編寫GroovyFX代碼變得干凈快捷。
控件和布局
JavaFX附帶了一套完整的現代UI控件,如按鈕、標簽、文本字段和復選框。還包括更復雜的控件,如ListView、TreeView和TableView。JavaFX還包括一組功能強大的布局,如HBox、VBox、BorderPane、TilePane和功能強大且靈活的GridPane。所有這些控件和布局窗格都只是JavaFX場景圖中的節(jié)點。如清單1所示,任何作為布局窗格子級的場景圖節(jié)點都將自動由該布局窗格設置其位置和大?。ɡ缱鳛镠box子級的兩個文本節(jié)點)。從技術上講,在布局期間還有其他因素起作用,例如節(jié)點的托管屬性的值以及節(jié)點是否可調整大小,但在絕大多數情況下,您可以簡單地假設布局窗格將控制其子節(jié)點的大小和位置。
某些布局窗格需要其他信息來布局其子節(jié)點。BorderPane需要知道節(jié)點是應該放置在布局空間的北、南、東、西還是中心。GridPane需要知道在哪個行和列中放置節(jié)點。如果您使用的是Java,則需要通過其他方法調用來設置這些約束。在GroovyFX中,這些約束可以直接傳遞到節(jié)點的屬性映射,GroovyFX將負責為您調用約束方法。這允許您將布局約束保留在聲明節(jié)點的同一位置,并使布局更易于理解。清單2中有一個這樣的例子,其中GroovyFX使用放置在GridPane中的各種控件來構建一個簡單的表單。
清單2:
import static groovyx.javafx.GroovyFX.start
start {
stage(title: "GridPane Demo", width: 400, height: 500, visible: true) {
scene(fill: groovyblue) {
gridPane(hgap: 5, vgap: 10, padding: 25, alignment: "top_center") {
columnConstraints(minWidth: 50, halignment: "right")
columnConstraints(prefWidth: 250, hgrow: 'always')
label("Please Send Us Your Feedback", style: "-fx-font-size: 18px;",
textFill: white, row: 0, columnSpan: 2, halignment: "center",
margin: [0, 0, 10]) {
onMouseEntered { e -> e.source.parent.gridLinesVisible = true }
onMouseExited { e -> e.source.parent.gridLinesVisible = false }
}
label("Name", hgrow: "never", row: 1, column: 0, textFill: white)
textField(promptText: "Your name", row: 1, column: 1 )
label("Email", row: 2, column: 0, textFill: white)
textField(promptText: "Your email address", row: 2, column: 1)
label("Message", row: 3, column: 0, valignment: "baseline",
textFill: white)
textArea(prefRowCount: 8, row: 3, column: 1, vgrow: 'always')
button("Send Message", row: 4, column: 1, halignment: "right")
}
}
}
}
清單2展示了GroovyFX的更多便利。您將注意到,GridPane的對齊方式設置為“topu center”。GroovyFX會發(fā)現您實際上引用的是枚舉值“位置頂部u中心因為GridPane的alignment屬性是Pos類型。設置halignment為“center”時也是如此(HPos中心).
GroovyFX允許的另一個節(jié)省時間的便利是將事件處理程序定義為Groovy閉包。這可以在清單2中第一個label節(jié)點上聲明的onMouseEntered和onmouseexted事件處理程序中看到。這兩個事件處理程序使GridPane單元格的輪廓在鼠標懸停在標簽上時可見。在GridPane中調試布局問題時,這是一個非常方便的技巧。清單2中的代碼創(chuàng)建的表單如圖2所示。
圖形和動畫
JavaFX還以其強大的圖形和動畫功能而聞名。GroovyFX在這些領域自然也有充分的支持。以清單3所示的代碼為例,它是由Oracle的JavaFX團隊編寫的基于Java的彩色圓圈示例應用程序的GroovyFX翻譯。
清單3:
import static groovyx.javafx.GroovyFX.start
start {
def circles
stage(title: 'GroovyFX ColorfulCircles', resizable: false, show: true) {
scene(width: 800, height: 600, fill: 'black') {
group {
circles = group {
30.times {
circle(radius: 200, fill: rgb(255, 255, 255, 0.05),
stroke: rgb(255, 255, 255, 0.16),
strokeWidth: 4, strokeType: 'outside')
}
effect boxBlur(width: 10, height: 10, iterations: 3)
}
rectangle(width: 800, height: 600, blendMode: 'overlay') {
def stops = ['#f8bd55', '#c0fe56', '#5dfbc1', '#64c2f8',
'#be4af7', '#ed5fc2', '#ef504c', '#f2660f']
fill linearGradient(start: [0f, 1f], end: [1f, 0f], stops: stops)
}
}
}
parallelTransition(cycleCount: 'indefinite', autoReverse: true) {
def random = new Random()
circles.children.each { circle -> translateTransition(40.s, node: circle, fromX: random.nextInt(800),
fromY: random.nextInt(600),
toX: random.nextInt(800),
toY: random.nextInt(600))
}
}.play()
}
}
}
清單3演示了GroovyFX對JavaFX形狀類(如Circle和Rectangle)的支持,以及對所有效果(如BoxBlur)的支持。使用Groovy循環(huán)構造(如30.times)來創(chuàng)建圓顯示了使用Groovy的生成器語法的一個很好的優(yōu)點:任何Groovy表達式或語句在生成器中都是有效的。這甚至包括這樣的構造,比如if語句,它允許您有條件地構建節(jié)點。
動畫無疑是JavaFX的優(yōu)點之一。您可以定義自己的時間線或使用許多可用的預打包轉換類中的一個。清單3演示了ParallelTransition(并行運行其他動畫的轉換)和TranslateTransition(更改節(jié)點的x、y坐標以便移動節(jié)點的轉換)的使用。在這種情況下,對每個圓應用隨機翻譯,以便它們在屏幕上慢慢地漫游。此應用程序的輸出如圖3所示。
FXBindable注解
javafxscript(用于編寫javafx1.x應用程序的語言)的一個非常強大的功能是它對綁定的內置支持。這個特性以屬性和綁定API類的形式存在于基于Java的JavaFX2.x庫中。這是一個流暢的API,允許您使用舊JavaFX腳本綁定功能的幾乎所有功能。基于Java的API的缺點之一是定義綁定類能夠使用的屬性所需的樣板代碼量。以清單4所示的Person類為例。
清單4:
public class Person {
private StringProperty firstName;
public void setFirstName(String val) { firstNameProperty().set(val); }
public String getFirstName() { return firstNameProperty().get(); }
public StringProperty firstNameProperty() {
if (firstName == null)
firstName = new SimpleStringProperty(this, "firstName");
return firstName;
}
private StringProperty lastName;
public void setLastName(String value) { lastNameProperty().set(value); }
public String getLastName() { return lastNameProperty().get(); }
public StringProperty lastNameProperty() {
if (lastName == null) // etc.
}
}
此清單顯示了在JavaFX中定義具有兩個屬性的類所需的典型樣板。由于這些屬性由StringProperty類支持,因此它們能夠完全參與所有JavaFX綁定功能。但是,如果您使用該樣板文件并將其乘以應用程序中每個類的每個屬性,您可能會很快對它引入的大量額外代碼感到苦惱,這些代碼必須由您(或其他不幸的開發(fā)人員)進行調試和維護。
GroovyFX可以利用Groovy最強大的特性之一AST轉換來解決這個問題。編寫自定義AST轉換允許您在編譯時修改或插入代碼,以減輕開發(fā)人員的編碼負擔。您所要做的就是用@FXBindable注釋來注釋一個標準的Groovy屬性,GroovyFX將為您編寫所有的樣板代碼!清單5顯示了Person類在使用@FXBindable注釋時的外觀。信不信由你,這段代碼與清單4所示的代碼是等價的。
清單5
public class Person {
@FXBindable String firstName;
@FXBindable String lastName;
}
如果POGO中的所有屬性都應該是可綁定的,那么可以對類進行注釋,而不是對每個屬性進行注釋,如清單6所示。
@FXBindable
public class Person {
String firstName;
String lastName;
}
為了進一步了解@FXBindable和GroovyFX的綁定功能,我建議您查看GitHub上GroovyFX項目中的AnalogClockDemo。
是時候寫一份完整的申請了?
當編寫一個復雜的應用程序時,您通常需要一些支持,比如使用MVC設計模式、簡單的線程,或者事件總線。這是Griffon的領域,一個易于使用的類似于Grails的框架,用于編寫桌面Java應用程序。
您會很高興地知道,遷移到Griffon并不意味著您需要放棄JavaFX的強大功能和GroovyFX的便利。Griffon有一個JavaFX插件,允許您使用GroovyFX編寫應用程序的視圖代碼。griffonjavafx原型的GitHub頁面上包含了入門說明。這個原型允許您快速啟動并運行一個新的javafxgriffon應用程序。
作者介紹