Javafx 将子项添加到边框窗格中央可调整顶部按钮的大小

Javafx 将子项添加到边框窗格中央可调整顶部按钮的大小,javafx,tornadofx,Javafx,Tornadofx,我目前正在将JavaFx应用程序迁移到TornadoFx。我想在单击按钮时添加图表。我最终得到了以下精简的代码: borderpane { prefWidth = 1000.0 prefHeight = 750.0 padding = insets(10) top = vbox { spacing = 5.0 hbox { spacing = 5.0 alignment = Pos.C

我目前正在将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)
        }
    }

您不小心将折线图添加到按钮中。了解构建器的工作方式非常重要-如果在节点上调用构建器函数,例如
linechart()
,新组件将添加到该节点。所以,你现在要做的是:

button("Show") {
    action {
         centerRef.add(linechart(...))
    }
}
这告诉框架在按钮内部创建一个折线图,然后将其添加到centerRef。您实际上正在呼叫
this@button.linechart()
。构建器的任务不仅仅是构建元素,还包括将其附加到其父元素。因此,只需调用
centerRef.linechart(..)
即可解决问题

您应该尽量避免依赖其他UI元素,并在组件之间保留尽可能少的引用。以下示例使用事件来减少耦合:

// 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)
                    }
                }
            }
        })
    }
}
//包含将在给定节点内构造图表的生成器的事件
类ChartAddEvent(val builder:Node.(->Unit):FXEvent()
类MainView:View(){
覆盖val root=borderpane{
setPrefSize(1000.0750.0)
paddingAll=10
top=hbox(5){
//调用addChart函数
按钮(“显示”)。操作(::添加图表)
}
中心=vbox{
订阅{事件->
//删除现有子项
清除()
//以vbox作为其父级调用事件内部的生成器
事件生成器(this@vbox)
}
}
}
//使用构建图表的生成器启动ChartAddEvent
//在事件订阅服务器指定的节点内
私人娱乐挂图(){
消防(安全)通风口{
val序列数据=(1..25)
.map{Random().nextDouble()}
.zip((1..25).map{Random().nextDouble()})
.toMap()
线形图(“我的图表”,NumberAxis(),NumberAxis()){
系列(“我的系列”){
对于((k,v)系列数据){
数据(k,v)
}
}
}
})
}
}