Добавление дочернего элемента в центральную кнопку изменения размера границы в верхней части

В настоящее время я переношу приложение 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 = [email protected] 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)
        }
    }

person spaenigs    schedule 19.06.2018    source источник


Ответы (1)


Вы случайно добавляете линейную диаграмму к своей кнопке. Чрезвычайно важно понимать, как работают компоновщики — если вы вызываете функцию компоновщика, например, linechart() на узле, новый компонент будет добавлен к этому узлу. Итак, вы делаете:

button("Show") {
    action {
         centerRef.add(linechart(...))
    }
}

Это говорит платформе создать линейную диаграмму внутри кнопки, а затем добавить ее в centerRef. На самом деле вы звоните [email protected](). Работа строителей заключается не только в создании элемента, но и в присоединении его к родительскому элементу. Таким образом, вы можете решить свою проблему, просто позвонив вместо этого 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)
                    }
                }
            }
        })
    }
}
person Edvin Syse    schedule 20.06.2018