Добавление дочернего элемента в центр бордюра по кнопке изменения размера в верхней части
В настоящее время я перемещаю приложение JavaFx в TornadoFx. Я хотел бы добавить график по нажатию кнопки. Я получил следующий урезанный код:
borderpane {
prefWidth = 1000.0
prefHeight = 750.0
padding = insets(10)
top = vbox {
spacing = 5.0
hbox {
spacing = 5.0
alignment = Pos.CENTER_LEFT
button("Show") {
action {
val centerRef = this@borderpane.center as VBox
println(centerRef.id)
if (centerRef.children.size > 0)
centerRef.children.removeAll(centerRef.children)
val seriesData = (1..25)
.map { Random().nextDouble() }
.zip((1..25).map { Random().nextDouble() })
.toMap()
centerRef.add(linechart("My Chart", NumberAxis(), NumberAxis()) {
series("my series") {
for ((k,v) in seriesData) {
data(k, v)
}
}
})
}
}
}
separator()
}
center = vbox { id = "centervbox" }
}
К сожалению, как только событие запускается, кнопка изменяется. Я пытался установить максимальную ширину и высоту кнопок, но настройки игнорируются. Я новичок в Kotlin и TornadoFx (хотя некоторый опыт работы с JavaFx) и действительно ценю любые предложения.
Заранее спасибо и всего наилучшего.
Редактировать: я получаю то же странное поведение с этим кодом, то есть первый график находится внутри кнопки. Только после второго клика график добавляется в VBox правильно.
vbox {
prefWidth = 1000.0
prefHeight = 750.0
id = "rootvbox"
button("button1") {
action {
val vbRef = this@vbox
println(vbRef.id)
val lc = linechart("My Chart", NumberAxis(), NumberAxis()) {
series("my series") {
for ((k,v) in (1..25).map { Random().nextDouble() }.zip((1..25).map { Random().nextDouble() }).toMap()) {
data(k, v)
}
}
}
vbRef.children.add(lc)
}
}
1 ответ
Вы случайно добавляете линейную диаграмму к своей кнопке. Чрезвычайно важно понять, как работают компоновщики - например, если вы вызываете функцию компоновщика linechart()
на узле новый компонент будет добавлен к этому узлу. Итак, здесь вы делаете:
button("Show") {
action {
centerRef.add(linechart(...))
}
}
Это говорит фреймворку создать линейную диаграмму внутри кнопки, а затем добавить ее в centerRef. Вы на самом деле звоните this@button.linechart()
, Работа строителей заключается не только в создании элемента, но и в прикреплении его к родительскому элементу. Таким образом, вы можете решить вашу проблему, просто позвонив centerRef.linechart(..)
вместо.
Вы должны стараться не полагаться на другие элементы пользовательского интерфейса и сохранять как можно меньше ссылок между компонентами. В следующем примере используются события для уменьшения связи:
// An event containing a builder that will construct the chart inside the given Node
class ChartAddEvent(val builder: Node.() -> Unit) : FXEvent()
class MainView : View() {
override val root = borderpane {
setPrefSize(1000.0, 750.0)
paddingAll = 10
top = hbox(5) {
// Call the addChart function
button("Show").action(::addChart)
}
center = vbox {
subscribe<ChartAddEvent> { event ->
// Remove existing children
clear()
// Call the builder inside the event with the vbox as it's parent
event.builder(this@vbox)
}
}
}
// Fire a ChartAddEvent with a builder that will construct the chart
// inside a node designated by the event subscriber
private fun addChart() {
fire(ChartAddEvent {
val seriesData = (1..25)
.map { Random().nextDouble() }
.zip((1..25).map { Random().nextDouble() })
.toMap()
linechart("My Chart", NumberAxis(), NumberAxis()) {
series("my series") {
for ((k, v) in seriesData) {
data(k, v)
}
}
}
})
}
}