Stage和Scene其實(shí)也沒什么好介紹的,只有些小改動(dòng)而已,
其它布局類的用法,后面文章會(huì)介紹。
下面直接用登陸窗口案例感受一下,
利用擴(kuò)展函數(shù)createWindow直接創(chuàng)建窗口,第一參數(shù)可以寫,也可以不寫,
如果寫就用傳進(jìn)來的Stage對(duì)象創(chuàng)建,如果不寫,函數(shù)內(nèi)部會(huì)自動(dòng)創(chuàng)建一個(gè)窗口。
下面啟動(dòng)程序,創(chuàng)建一個(gè)窗口,窗口內(nèi)容是一個(gè)Button按鈕
fun main(args: Array<String>) {
KApplication.launch(args){
createWindow(it,"登陸窗口",300.0,200.0){KButton("Button")}
}
}
效果如下

由于Button當(dāng)做的根節(jié)點(diǎn),所以默認(rèn)大小布滿整個(gè)窗口,這是意料之中的事情
接下來開始用布局當(dāng)做根節(jié)點(diǎn)
一個(gè)登陸窗口,基本結(jié)構(gòu)是,三行三列,如下結(jié)構(gòu)
賬號(hào) 輸入框
密碼 輸入框
注冊(cè) 登陸
那么可以利用垂直布局VBox和水平布局HBox組合,進(jìn)行組合達(dá)到效果
一把登陸窗口都是禁止拉伸的,先把窗口屬性添加上,然后下面再布局
fun main(args: Array<String>) {
KApplication.launch(args){
createWindow(it,"登陸窗口",300.0,200.0){
isResizable=false //禁止窗口拉伸
VBoxLayout {
HBoxLayout { view(KLabel("賬號(hào):"),KTextField())}
HBoxLayout { view(KLabel("密碼:"),KPasswordField()) }
HBoxLayout { view(KButton("注冊(cè)"),KButton("登陸"))}
}
}
}
}
如圖所示

擴(kuò)展庫已經(jīng)將JavaFX當(dāng)中所有的布局類都進(jìn)行了擴(kuò)展,結(jié)尾都加了Layout,
并且會(huì)自動(dòng)添加到外層控件里,所有才有上面的寫法,不需要手動(dòng)children.add
而且可以看出,布局結(jié)構(gòu)已經(jīng)有了,只是有些細(xì)節(jié)需要添加,特別是對(duì)齊方式。
首選我需要讓VBox的子控件都居中,直接子控件是三個(gè)HBox,然后再讓這三個(gè)HBox的子控件居中
這樣,所有內(nèi)容都會(huì)居中,效果會(huì)更好看
fun main(args: Array<String>) {
KApplication.launch(args){
createWindow(it,"登陸窗口",300.0,200.0){
isResizable=false //禁止窗口拉伸
VBoxLayout {
alignment=Pos.CENTER
HBoxLayout { view(KLabel("賬號(hào):"),KTextField())}.alignment=Pos.CENTER
HBoxLayout { view(KLabel("密碼:"),KPasswordField()) }.alignment=Pos.CENTER
HBoxLayout { view(KButton("注冊(cè)"),KButton("登陸"))}.alignment=Pos.CENTER
}
}
}
}
如圖所示

三個(gè)HBox的對(duì)齊方式都是居中,我寫了三個(gè),如果有100個(gè)控件,是不是要寫100次,
答案是否定的,只需要拿到VBox子集合列表,做個(gè)循環(huán)統(tǒng)一設(shè)置就行了。
于是我在每個(gè)布局類的內(nèi)部,擴(kuò)展了childrenSet函數(shù),可以遍歷子節(jié)點(diǎn),同時(shí)遍歷參數(shù)里還會(huì)把子控件在第幾位的索引也傳進(jìn)去
這一點(diǎn)比forEach要強(qiáng),因?yàn)閒orEach沒辦法拿到索引,除非寫額外代碼
fun main(args: Array<String>) {
KApplication.launch(args){
createWindow(it,"登陸窗口",300.0,200.0){
isResizable=false //禁止窗口拉伸
VBoxLayout {
alignment=Pos.CENTER
HBoxLayout { view(KLabel("賬號(hào):"),KTextField())}
HBoxLayout { view(KLabel("密碼:"),KPasswordField()) }
HBoxLayout { view(KButton("注冊(cè)"),KButton("登陸"))}
childrenSet { this as KHBox;alignment=Pos.CENTER }
}
}
}
}
效果跟上圖一樣
childrenSet 是一個(gè)通用類型的方式,他的泛型只能指定Node,所以內(nèi)部需要做個(gè)類型轉(zhuǎn)換,必要時(shí)還得用if判斷,轉(zhuǎn)成不同子類型
下面繼續(xù)改寫,雖然已經(jīng)居中了,但是太過于緊湊,那么給VBox和HBox都添加一個(gè)spacing屬性間距,這樣會(huì)好看一些
fun main(args: Array<String>) {
KApplication.launch(args){
createWindow(it,"登陸窗口",300.0,200.0){
isResizable=false
VBoxLayout {
alignment=Pos.CENTER
spacing=15.0
HBoxLayout { view(KLabel("賬號(hào):"),KTextField())}
HBoxLayout { view(KLabel("密碼:"),KPasswordField()) }
HBoxLayout { view(KButton("注冊(cè)"),KButton("登陸"))}
childrenSet { this as KHBox;alignment=Pos.CENTER;spacing=10.0}
}
}
}
}
效果如圖

效果還可以,只是兩個(gè)Button按鈕,離得太近了,可以單獨(dú)讓最后一行的HBox間距大一點(diǎn)
不過沒必要單獨(dú)寫,只需要在childrenSet 里面寫就行,利用傳進(jìn)來的子控件索引,和if語句區(qū)分差異化即可
fun main(args: Array<String>) {
KApplication.launch(args){
createWindow(it,"登陸窗口",300.0,200.0){
isResizable=false //禁止窗口拉伸
VBoxLayout {
alignment=Pos.CENTER
spacing=15.0
HBoxLayout { view(KLabel("賬號(hào):"),KTextField())}
HBoxLayout { view(KLabel("密碼:"),KPasswordField()) }
HBoxLayout { view(KButton("注冊(cè)"),KButton("登陸"))}
childrenSet { this as KHBox;alignment=Pos.CENTER;spacing=if(it==2) 80.0 else 10.0}
}
}
}
}
如圖所示

這樣一個(gè)登陸窗口就完成了,從啟動(dòng)程序到布局調(diào)整,不到20行代碼
另外解釋一下 spacing=if(it==2) 80.0 else 10.0 這句話
it表示childrenSet 傳進(jìn)來的子控件索引位置,2就表示索引為2,也就是最后一行的HBox
然后設(shè)置它的間隔,等2表示最后一行的HBox間隔設(shè)置80,其它的都設(shè)置10
這篇文章就到這,下一篇文章再講,Button按鈕和輸入框該如何交互,該如何設(shè)置里面這些控件的屬性