譯自《Layouts and Menus》
布局和菜單
復(fù)雜的UI需要很多控件捞奕。 這些控件可能需要使用設(shè)置策略(set policies),進(jìn)行分組拄轻,定位并調(diào)整大小颅围。 幸運(yùn)的是,TornadoFX簡(jiǎn)化了JavaFX自帶的許多布局(layouts)恨搓,并且具有自己的專有Form
布局院促。
TornadoFX還具有類型安全的構(gòu)建器(type-safe builders),以高度結(jié)構(gòu)化斧抱,聲明性的方式創(chuàng)建菜單常拓。 使用常規(guī)JavaFX代碼構(gòu)建菜單尤其繁瑣,而Kotlin在這個(gè)部分真的很出色辉浦。
布局構(gòu)建器(Builders for Layouts)
布局(Layouts)將控制分組弄抬,并設(shè)置有關(guān)其大小和定位行為的策略(policies)。 在技??術(shù)上宪郊,布局(layouts)本身就是控件掂恕,因此您可以在布局中嵌套布局。 這對(duì)于構(gòu)建復(fù)雜的UI來(lái)說(shuō)至關(guān)重要弛槐,而TornadoFX可以通過(guò)明顯地顯示嵌套關(guān)系來(lái)簡(jiǎn)化UI代碼的維護(hù)懊亡。
VBox
VBox按照控件在其塊中聲明的順序垂直堆疊控件(圖7.1)。
vbox {
button("Button 1").setOnAction {
println("Button 1 Pressed")
}
button("Button 2").setOnAction {
println("Button 2 Pressed")
}
}
您還可以在子控件的塊中調(diào)用vboxConstraints()
來(lái)更改VBox
的邊距(margin)和垂直增長(zhǎng)(vertical growing)行為乎串。
vbox {
button("Button 1") {
vboxConstraints {
marginBottom = 20.0
vGrow = Priority.ALWAYS
}
}
button("Button 2")
}
您可以用vGrow
速記擴(kuò)展屬性(shorthand extension property)店枣,而無(wú)需調(diào)用vboxConstraints()
。
vbox {
button("Button 1") {
vGrow = Priority.ALWAYS
}
button("Button 2")
}
HBox
HBox
行為幾乎與VBox
相同叹誉,但是按照其塊中聲明的順序從左到右水平堆疊所有控件艰争。
hbox {
button("Button 1").setOnAction {
println("Button 1 Pressed")
}
button("Button 2").setOnAction {
println("Button 2 Pressed")
}
}
您還可以在子控件的塊內(nèi)調(diào)用hboxConstraints()
來(lái)更改HBox
的邊距(margin)和橫向增長(zhǎng)(horizontal growing behaviors)行為。
hbox {
button("Button 1") {
hboxConstraints {
marginRight = 20.0
hGrow = Priority.ALWAYS
}
}
button("Button 2")
}
您可以使用hGrow
縮寫(xiě)擴(kuò)展屬性(shorthand extension property)桂对,而不調(diào)用hboxConstraints()
甩卓。
hbox {
button("Button 1") {
hGrow = Priority.ALWAYS
}
button("Button 2")
}
FlowPane
FlowPane
控件從左至右布局控件,并在到達(dá)邊界時(shí)將其轉(zhuǎn)到下一行蕉斜。 例如逾柿,假設(shè)您添加了100個(gè)按鈕到FlowPane
(圖7.3)缀棍。你會(huì)注意到它只是從左到右布置按鈕,當(dāng)它耗盡空間時(shí)机错,它移動(dòng)到“下一行”爬范。
flowpane {
for (i in 1..100) {
button(i.toString()) {
setOnAction { println("You pressed button $i") }
}
}
}
請(qǐng)注意,當(dāng)您調(diào)整窗口大小時(shí)弱匪, FlowLayout
將重新布局按鈕青瀑,以使它們都可以適合(圖7.4)
FlowLayout
不經(jīng)常使用,因?yàn)樘幚泶罅靠丶ǔJ呛?jiǎn)單的萧诫,但它可以在某些情況下派上用場(chǎng)斥难,也可以在其他布局中使用。
BorderPane
BorderPane
是一個(gè)非常有用的布局帘饶,將控件分為5個(gè)區(qū)域: top
哑诊, left
, bottom
及刻, right
和center
镀裤。 可以使用這些區(qū)域的兩個(gè)或更多來(lái)來(lái)保存控件,很容易地構(gòu)建許多UI(圖7.5)缴饭。
borderpane {
top = label("TOP") {
useMaxWidth = true
style {
backgroundColor = Color.RED
}
}
bottom = label("BOTTOM") {
useMaxWidth = true
style {
backgroundColor = Color.BLUE
}
}
left = label("LEFT") {
useMaxWidth = true
style {
backgroundColor = Color.GREEN
}
}
right = label("RIGHT") {
useMaxWidth = true
style {
backgroundColor = Color.PURPLE
}
}
center = label("CENTER") {
useMaxWidth = true
style {
backgroundColor = Color.YELLOW
}
}
}
您會(huì)注意到top
和bottom
區(qū)域占據(jù)整個(gè)水平空間暑劝,而left
, center
颗搂, right
必須共享可用的水平空間担猛。 但center
有權(quán)獲得任何額外的可用空間(垂直和水平),使其成為像TableView
這樣的大型控件的理想選擇峭火。 例如毁习,您可以在left
區(qū)域中垂直堆疊一些按鈕,并將TableView
放在center區(qū)域(圖7.6)卖丸。
borderpane {
left = vbox {
button("REFRESH")
button("COMMIT")
}
center = tableview<Person> {
items = listOf(
Person("Joe Thompson", 33),
Person("Sam Smith", 29),
Person("Nancy Reams", 41)
).observable()
column("NAME",Person::name)
column("AGE",Person::age)
}
}
BorderPane
是您可能想要經(jīng)常使用的布局纺且,因?yàn)樗?jiǎn)化了許多復(fù)雜的UI。top
區(qū)域通常用于保存MenuBar
稍浆, bottom
區(qū)域通常保持某種狀態(tài)欄载碌。 您已經(jīng)看到center
保持焦點(diǎn)控制,如TableView
衅枫, left
和right
保持側(cè)面板與任何不適合放在MenuBar
中的外圍控件(如按鈕或工具欄) 嫁艇。 本節(jié)稍后將介紹菜單。
表單生成器
TornadoFX有一個(gè)有用的Form
控件來(lái)處理大量的用戶輸入弦撩。 擁有多個(gè)輸入字段以獲取用戶信息是常見(jiàn)的步咪,JavaFX沒(méi)有內(nèi)置的解決方案來(lái)簡(jiǎn)化此操作。 為了解決這個(gè)問(wèn)題益楼,TornadoFX有一個(gè)構(gòu)建器來(lái)聲明具有任意數(shù)量字段的Form
(圖7.7)猾漫。
form {
fieldset("Personal Info") {
field("First Name") {
textfield()
}
field("Last Name") {
textfield()
}
field("Birthday") {
datepicker()
}
}
fieldset("Contact") {
field("Phone") {
textfield()
}
field("Email") {
textfield()
}
}
button("Commit") {
action { println("Wrote to database!")}
}
}
是不是很棒? 您可以為每個(gè)字段指定一個(gè)或多個(gè)控件点晴, Form
將為您呈現(xiàn)分組和標(biāo)簽。
您也可以選擇在輸入字段之上布置標(biāo)簽:
fieldset("FieldSet", labelPosition = VERTICAL)
每個(gè)field
都包含一個(gè)內(nèi)有標(biāo)簽的容器悯周,另一個(gè)容器用于在其中添加的輸入字段粒督。 默認(rèn)情況下,輸入字段的容器是HBox
禽翼,這意味著單個(gè)字段中的多個(gè)輸入將彼此水平相鄰布置屠橄。 您可以指定一個(gè)字段的orientation
參數(shù),使其在多個(gè)輸入之間相互上下排列闰挡。 垂直取向的另一個(gè)用例是允許輸入隨著垂直方向的擴(kuò)展而增長(zhǎng)锐墙。 這對(duì)于在表單中顯示TextAreas
非常方便:
form {
fieldset("Feedback Form", labelPosition = VERTICAL) {
field("Comment", VERTICAL) {
textarea {
prefRowCount = 5
vgrow = Priority.ALWAYS
}
}
buttonbar {
button("Send")
}
}
}
上面的示例還使用buttonbar
構(gòu)建器創(chuàng)建一個(gè)沒(méi)有標(biāo)簽的特殊字段,同時(shí)保留標(biāo)簽縮進(jìn)解总,使按鈕在輸入框下排列贮匕。
您將每個(gè)輸入綁定到一個(gè)模型(model)姐仅,您可以將控件布局的渲染留給Form
花枫。 因此,如果可能掏膏,您可能希望在GridPane
上使用它劳翰,接下來(lái)我們將介紹。
在Form
內(nèi)嵌套布局(Nesting layouts inside a Form)
您可以使用您選擇的任何布局容器來(lái)包裝fieldets
和fields
馒疹,以創(chuàng)建復(fù)雜的表單布局佳簸。
form {
hbox(20) {
fieldset("Left FieldSet") {
hbox(20) {
vbox {
field("Field l1a") { textfield() }
field("Field l2a") { textfield() }
}
vbox {
field("Field l1b") { textfield() }
field("Field l2b") { textfield() }
}
}
}
fieldset("Right FieldSet") {
hbox(20) {
vbox {
field("Field r1a") { textfield() }
field("Field r2a") { textfield() }
}
vbox {
field("Field r1b") { textfield() }
field("Field r2b") { textfield() }
}
}
}
}
}
GridPane
如果你想對(duì)控件的布局進(jìn)行細(xì)致的管理, GridPane
會(huì)給你很多的颖变。 當(dāng)然生均,它需要更多的配置和代碼樣板。 在繼續(xù)使用GridPane
之前腥刹,您可能需要考慮使用為您抽象了布局配置的Form
或其他布局马胧。
使用GridPane
的一種方法是聲明每row
的內(nèi)容。 對(duì)于任何給定的Node
您可以調(diào)用其gridpaneConstraints
來(lái)配置該Node
的各種GridPane
行為衔峰,例如margin
和columnSpan
(圖7.10)
gridpane {
row {
button("North") {
useMaxWidth = true
gridpaneConstraints {
marginBottom = 10.0
columnSpan = 2
}
}
}
row {
button("West")
button("East")
}
row {
button("South") {
useMaxWidth = true
gridpaneConstraints {
marginTop = 10.0
columnSpan = 2
}
}
}
}
請(qǐng)注意佩脊,在每行之間,如果在其gridpaneConstraints
內(nèi)分別為“North”和“South”按鈕的marginBottom
和marginTop
聲明了每行之間的距離為10.0 垫卤。
或者威彰,您可以顯式指定每個(gè)Node
的列/行索引位置,而不是聲明每row
的控件穴肘。 這將完成我們之前建立的精確布局歇盼,但是使用列/行索引來(lái)規(guī)范。 它有點(diǎn)冗長(zhǎng)评抚,但它可以更加明確地控制控件的位置豹缀。
gridpane {
button("North") {
useMaxWidth = true
gridpaneConstraints {
columnRowIndex(0,0)
marginBottom = 10.0
columnSpan = 2
}
}
button("West").gridpaneConstraints {
columnRowIndex(0,1)
}
button("East").gridpaneConstraints {
columnRowIndex(1,1)
}
button("South") {
useMaxWidth = true
gridpaneConstraints {
columnRowIndex(0,2)
marginTop = 10.0
columnSpan = 2
}
}
}
這些都是您可以在給定Node
上修改的gridpaneConstraints
屬性赵讯。 一些表示為可以賦值的簡(jiǎn)單屬性,而其他屬性可以通過(guò)函數(shù)賦值耿眉。
屬性 | 描述 |
---|---|
columnIndex:Int | 給定控件的列索引 |
rowIndex:Int | 給定控件的行索引 |
columnRowIndex(columnIndex:Int边翼,rowIndex:Int) | 指定行和列索引 |
columnSpan:Int | 控件占用的列數(shù) |
rowSpan:Int | 控制占用的行數(shù) |
hGrow:Priority | 水平增長(zhǎng)優(yōu)先 |
vGrow:Priority | 垂直成長(zhǎng)優(yōu)先 |
vhGrow:Priority | 為vGrow和hGrow指定相同的優(yōu)先級(jí) |
fillHeight:Boolean | 設(shè)置Node 是否填充其區(qū)域的高度 |
fillWidth:Boolean | 設(shè)置Node 是否填充其區(qū)域的寬度 |
fillHeightWidth:Boolean | 設(shè)置Node 是否填充高度和寬度的區(qū)域 |
hAlignment:HPos | 水平對(duì)齊政策 |
vAlignment:VPos | 垂直對(duì)齊策略 |
margin:Int |
Node 所有四邊的邊距 |
marginBottom:Int |
Node 底部的邊距 |
marginTop:Int |
Node 頂端的邊距 |
marginLeft:Int |
Node 左側(cè)的左邊距 |
marginRight:Int |
Node 右側(cè)的右邊距 |
marginLeftRight:Int |
Node 的右邊距和左邊距 |
marginTopBottom:Int |
Node 的頂部和底部邊距 |
另外,如果需要配置ColumnConstraints
鸣剪,可以在GridPane
本身的GridPane Node
上調(diào)用gridpaneColumnConstraints
组底,也可以調(diào)用constraintsForColumn(columnIndex)
。
gridpane {
row {
button("Left") {
gridpaneColumnConstraints {
percentWidth = 25.0
}
}
button("Middle")
button("Right")
}
constraintsForColumn(1).percentWidth = 50.0
}
StackPane
一個(gè)StackPane
是一個(gè)布局筐骇,您將不太經(jīng)常使用债鸡。 對(duì)于您添加的每個(gè)控件,它將逐字地堆疊在一起(literally stack them )铛纬,而不是像VBox
厌均,但是字面上覆蓋它們(literally overlay them)。
例如告唆,您可以創(chuàng)建一個(gè)“BOTTOM” Button
并在其頂部放置一個(gè)“TOP” Button
棺弊。 您聲明控件的順序?qū)⒁韵嗤捻樞驈牡撞康巾敳刻砑铀鼈儯▓D7.10)。
class MyView: View() {
override val root = stackpane {
button("BOTTOM") {
useMaxHeight = true
useMaxWidth = true
style {
backgroundColor += Color.AQUAMARINE
fontSize = 40.0.px
}
}
button("TOP") {
style {
backgroundColor += Color.WHITE
}
}
}
}
TabPane
TabPane
創(chuàng)建一個(gè)用“tab”分隔的不同屏幕的UI擒悬。 這允許通過(guò)點(diǎn)擊相應(yīng)的選項(xiàng)卡快速輕松地切換不同的屏幕(圖7.11)模她。 您可以聲明一個(gè)tabpane()
,然后根據(jù)需要聲明盡可能多的tab()
實(shí)例懂牧。 對(duì)于每個(gè)tab()
函數(shù)侈净,通過(guò)Tab
的名稱和父Node
控件來(lái)填充它。
tabpane {
tab("Screen 1", VBox()) {
button("Button 1")
button("Button 2")
}
tab("Screen 2", HBox()) {
button("Button 3")
button("Button 4")
}
}
TabePane
是分隔屏幕并組織大量控件的有效工具僧凤。 語(yǔ)法有些簡(jiǎn)潔畜侦,足以在tab()
塊中聲明像TableView
這樣的復(fù)雜控件(圖7.13)。
tabpane {
tab("Screen 1", VBox()) {
button("Button 1")
button("Button 2")
}
tab("Screen 2", HBox()) {
tableview<Person> {
items = listOf(
Person(1,"Samantha Stuart",LocalDate.of(1981,12,4)),
Person(2,"Tom Marks",LocalDate.of(2001,1,23)),
Person(3,"Stuart Gills",LocalDate.of(1989,5,23)),
Person(3,"Nicole Williams",LocalDate.of(1998,8,11))
).observable()
column("ID",Person::id)
column("Name", Person::name)
column("Birthday", Person::birthday)
column("Age",Person::age)
}
}
}
像許多構(gòu)建器一樣躯保, TabPane
有幾個(gè)屬性可以調(diào)整其選項(xiàng)卡的行為旋膳。 例如,您可以調(diào)用tabClosingPolicy
來(lái)去掉選項(xiàng)卡上的“X”按鈕吻氧,從而無(wú)法關(guān)閉溺忧。
class MyView: View() {
override val root = tabpane {
tabClosingPolicy = TabPane.TabClosingPolicy.UNAVAILABLE
tab("Screen 1", VBox()) {
button("Button 1")
button("Button 2")
}
tab("Screen 2", HBox()) {
button("Button 3")
button("Button 4")
}
}
}
菜單構(gòu)建器
以嚴(yán)格面向?qū)ο蟮姆绞綐?gòu)建菜單可能很麻煩。 但是使用類型安全的構(gòu)建器盯孙,Kotlin的函數(shù)結(jié)構(gòu)可以直觀地聲明嵌套的菜單層次結(jié)構(gòu)鲁森。
MenuBar,Menu和MenuItem
使用導(dǎo)航菜單在用戶界面上保留大量命令并不常見(jiàn)振惰。 例如歌溉, BorderPane
的top
區(qū)域通常是MenuBar
所在的地方。 在那里可以輕松添加菜單和子菜單(圖7.12)。
menubar {
menu("File") {
menu("Connect") {
item("Facebook")
item("Twitter")
}
item("Save")
item("Quit")
}
menu("Edit") {
item("Copy")
item("Paste")
}
}
您還可以選擇提供鍵盤快捷鍵痛垛,圖形以及每個(gè)item()
的action
函數(shù)參數(shù)草慧,以指定選定操作時(shí)的動(dòng)作(圖7.14)。
menubar {
menu("File") {
menu("Connect") {
item("Facebook", graphic = fbIcon).action { println("Connecting Facebook!") }
item("Twitter", graphic = twIcon).action { println("Connecting Twitter!") }
}
item("Save","Shortcut+S").action {
println("Saving!")
}
menu("Quit","Shortcut+Q").action {
println("Quitting!")
}
}
menu("Edit") {
item("Copy","Shortcut+C").action {
println("Copying!")
}
item("Paste","Shortcut+V").action {
println("Pasting!")
}
}
}
分隔線(Separators)
您可以在Menu
的兩個(gè)items
之間聲明一個(gè)separator()
來(lái)創(chuàng)建一個(gè)分隔線匙头。 這有助于給Menu
分組命令并將它們分開(kāi)(圖7.15)漫谷。
menu("File") {
menu("Connect") {
item("Facebook")
item("Twitter")
}
separator()
item("Save","Shortcut+S") {
println("Saving!")
}
item("Quit","Shortcut+Q") {
println("Quitting!")
}
}
上下文菜單(ContextMenu)
JavaFX中的大多數(shù)控件都有一個(gè)contextMenu
屬性,您可以在其中指定ContextMenu
實(shí)例蹂析。 這是一個(gè)在右鍵單擊控件時(shí)彈出的Menu
舔示。
一個(gè)ContextMenu
有函數(shù)可以添加Menu
和MenuItem
實(shí)例,就像MenuBar
一樣 电抚。 例如惕稻,將一個(gè)ContextMenu
添加到TableView<Person>
是有幫助的,并提供要在表格記錄上完成的命令(圖7.16)蝙叛。 有一個(gè)名為contextmenu
的構(gòu)建器將構(gòu)建一個(gè)ContextMenu
并將其賦值給控件的contextMenu
屬性俺祠。
tableview(persons) {
column("ID", Person::id)
column("Name", Person::name)
column("Birthday", Person::birthday)
column("Age", Person::age)
contextmenu {
item("Send Email").action {
selectedItem?.apply { println("Sending Email to $name") }
}
item("Change Status").action {
selectedItem?.apply { println("Changing Status for $name") }
}
}
}
注意還有可用的
RadioMenuItem
和CheckMenuItem
這些MenuItem
變體。
當(dāng)菜單被選為op
塊參數(shù)時(shí)借帘,menuitem
構(gòu)建器采取動(dòng)作來(lái)執(zhí)行蜘渣。 不幸的是,這破壞了其他構(gòu)建器姻蚓,其中op
塊對(duì)構(gòu)建器創(chuàng)建的元素進(jìn)行操作宋梧。 因此匣沼,引入item
構(gòu)建器作為替代狰挡,您可以在item
本身上操作,因此您必須調(diào)用setOnAction
來(lái)賦值動(dòng)作释涛。menuitem
構(gòu)建器沒(méi)有被棄用加叁,因?yàn)樗员?code>item構(gòu)建器更簡(jiǎn)潔的方式解決了常見(jiàn)情況。
ListMenu
TornadoFX帶有一個(gè)列表菜單(ListMenu
)唇撬,其行為和看起來(lái)更像是一個(gè)典型的基于ul/li
的HTML5菜單它匕。
以下代碼示例顯示如何使用構(gòu)建器模式的ListMenu
:
listmenu(theme = "blue") {
item(text = "Contacts", graphic = Styles.contactsIcon()) {
// Marks this item as active.
activeItem = this
whenSelected { /* Do some action */ }
}
item(text = "Projects", graphic = Styles.projectsIcon())
item(text = "Settings", graphic = Styles.settingsIcon())
}
以下屬性可用于配置ListMenu :
Css屬性(Css Properties)
偽類(Pseudo Classes)
看看ListMenu的默認(rèn)樣式表。
項(xiàng)目(Item)
item
構(gòu)建器允許以非常方便的方式為ListMenu
創(chuàng)建items
窖认。 支持以下語(yǔ)法:
item("SomeText", graphic = SomeNode, tag = SomeObject) {
// Marks this item as active.
activeItem = this
// Do some action when selected
whenSelected { /* Action */ }
}
填充父容器(Filling the parent container)
useMaxWidth
屬性可用于水平填充父容器豫柬。 useMaxHeight
屬性將垂直填充父容器。 這些屬性實(shí)際上適用于所有節(jié)點(diǎn)扑浸,但對(duì)ListMenu
特別有用烧给。
Squeezebox
JavaFX具有手風(fēng)琴(Accordion
)控件,可讓您將一組TilePanes
組合在一起喝噪,形成手風(fēng)琴控件(accordion of controls)础嫡。 JavaFX手風(fēng)琴(Accordion
)只允許您一次打開(kāi)單個(gè)手風(fēng)琴折疊(a single accordion fold),并且還有一些其他缺點(diǎn)。 為了解決這個(gè)問(wèn)題榴鼎,TornadoFX附帶了SqueezeBox
組件伯诬,其行為看起來(lái)非常類似于手風(fēng)琴(Accordion
),同時(shí)提供了一些增強(qiáng)功能巫财。
squeezebox {
fold("Customer Editor", expanded = true) {
form {
fieldset("Customer Details") {
field("Name") { textfield() }
field("Password") { textfield() }
}
}
}
fold("Some other editor", expanded = true) {
stackpane {
label("Nothing here")
}
}
}
一個(gè)
Squeezebox
顯示兩個(gè)折疊盗似,兩者都默認(rèn)擴(kuò)展。
您可以通過(guò)將multiselect = false
傳遞給構(gòu)建器構(gòu)造函數(shù)平项,使SqueezeBox
僅允許在任何給定時(shí)間展開(kāi)單個(gè)折疊桥言。
您可以選擇通過(guò)單擊標(biāo)題窗格右側(cè)的十字架(clicking a cross in the right corner of the title pane)而允許折疊成為可關(guān)閉的(allow folds to be closable)。 您可以通過(guò)將closeable = true
傳遞給fold構(gòu)建器葵礼,從而以每折為單位啟用關(guān)閉按鈕(enable the close buttons on a per fold basis)号阿。
squeezebox {
fold("Customer Editor", expanded = true, closeable = true) {
form {
fieldset("Customer Details") {
field("Name") { textfield() }
field("Password") { textfield() }
}
}
}
fold("Some other editor", closeable = true) {
stackpane {
label("Nothing here")
}
}
}
這個(gè)
SqueezeBox
有可關(guān)閉的折疊(closeable folds)。
closeable
屬性當(dāng)然可以結(jié)合expanded
鸳粉。
SqueezeBox
和Accordion
之間的另一個(gè)重要區(qū)別就是分配空間(distributes overflowing space)的方式扔涧。 手風(fēng)琴(Accordion
)將垂直延伸以填充其父容器,并將當(dāng)前打開(kāi)的任何折疊推至底部届谈。 如果父容器非常大枯夜,這將創(chuàng)建一個(gè)不自然的查看視圖。 在這方面艰山,擠壓框(SqueezeBox
)可能默認(rèn)就是您想要的湖雹,但您可以添加fillHeight = true
以獲得類似于Accordion
的外觀。
您可以像您一樣創(chuàng)建一個(gè)TitlePane
樣式一樣來(lái)創(chuàng)建SqueezeBox
樣式曙搬。 關(guān)閉按鈕有一個(gè)名為close-button
的css
類摔吏,容器有一個(gè)名為squeeze-box
的css
類。
Drawer
抽屜(Drawer)是一個(gè)非常像TabPane
的導(dǎo)航組件纵装,但它在父容器的任一側(cè)的垂直或水平放置的按鈕欄中組織每個(gè)抽屜項(xiàng)目龙助。 它類似于許多流行的業(yè)務(wù)應(yīng)用程序和IDE中發(fā)現(xiàn)的工具抽屜(tool drawers)抠藕。 當(dāng)選擇項(xiàng)目時(shí)桦卒,項(xiàng)目的內(nèi)容將顯示在跨越控件的高度或?qū)挾鹊膬?nèi)容區(qū)域中的按鈕旁邊或上方/下方鳖敷,以及內(nèi)容的首選寬度或高度,具體取決于是否將其屯彀Γ靠在父級(jí)的垂直或水平方面滤祖。 在多重選擇(multiselect
)模式下,您甚至可以同時(shí)打開(kāi)多個(gè)抽屜物品瓶籽,讓它們共享它們之間的空間匠童。 它們將始終按照相應(yīng)按鈕的順序打開(kāi)。
class DrawerView : View("TornadoFX Info Browser") {
override val root = drawer {
item("Screencasts", expanded = true) {
webview {
prefWidth = 470.0
engine.userAgent = iPhoneUserAgent
engine.load(TornadoFXScreencastsURI)
}
}
item("Links") {
listview(links) {
cellFormat { link ->
graphic = hyperlink(link.name) {
setOnAction {
hostServices.showDocument(link.uri)
}
}
}
}
}
item("People") {
tableview(people) {
column("Name", Person::name)
column("Nick", Person::nick)
}
}
}
class Link(val name: String, val uri: String)
class Person(val name: String, val nick: String)
// Sample data variables left out (iPhoneUserAgent, TornadoFXScreencastsURI, people and links)
}
抽屜可以配置為顯示右側(cè)的按鈕棘劣,您可以選擇同時(shí)支持打開(kāi)多個(gè)抽屜物品俏让。 當(dāng)以多重選擇模式運(yùn)行時(shí),內(nèi)容上方會(huì)出現(xiàn)一個(gè)標(biāo)題,這將有助于區(qū)分內(nèi)容區(qū)域中的項(xiàng)目首昔。 您可以使用布爾的showHeader
參數(shù)控制標(biāo)題外觀寡喝。 當(dāng)啟用多重選擇時(shí),它將默認(rèn)為true勒奇,否則為false预鬓。
drawer(side = Side.RIGHT, multiselect = true) {
// Everything else is identical
}
帶有右側(cè)按鈕的抽屜,多選模式和標(biāo)題窗格赊颠。
當(dāng)抽屜被添加到某物的旁邊時(shí)格二,您可以選擇抽屜的內(nèi)容區(qū)域是否應(yīng)替換其旁邊的節(jié)點(diǎn)(默認(rèn))或浮動(dòng)。 floatingContent
屬性默認(rèn)為false竣蹦,導(dǎo)致Drawer
替換其旁邊的內(nèi)容顶猜。
您可以使用Drawer
的maxContentSize
和fixedContentSize
屬性進(jìn)一步控制內(nèi)容區(qū)域的大小。 根據(jù)dockingSide
痘括,這些屬性將限制內(nèi)容區(qū)域的寬度或高度长窄。
Workspace
功能內(nèi)置支持抽屜控件。 任何Workspace
的leftDrawer
纲菌, rightDrawer
和bottomDrawer
屬性將允許您將抽屜項(xiàng)目bottomDrawer
在其中挠日。 在“工作區(qū)(Workspace
)”一章中了解更多信息。
轉(zhuǎn)換可觀察列表項(xiàng)并綁定到布局(Converting observable list items and binding to layouts)
TODO
總結(jié)
到目前為止翰舌,您應(yīng)該擁有能力可以使用布局嚣潜,標(biāo)簽窗格以及其他控件來(lái)管理控件。 將這些與數(shù)據(jù)控件結(jié)合使用椅贱,您應(yīng)該可以在一小部分時(shí)間內(nèi)轉(zhuǎn)換UI懂算。
當(dāng)涉及到構(gòu)建器時(shí),您已經(jīng)達(dá)到了頂峰(top of the peak)夜涕,并擁有所需要的所有成效犯犁。 剩下的所有內(nèi)容都是圖表和形狀(charts and shapes),我們將在接下來(lái)的兩章中介紹女器。