从列表属性到任意对象属性的javafx绑定

时间:2019-11-25 02:52:58

标签: javafx kotlin tornadofx

我正在尝试让一个类具有绑定到另一个类的list属性的属性,其中第一个属性是通过对列表中的对象进行汇总计算得出的。下面的代码是我的生产代码的简化版本。 (生产代码对DateTime对象进行汇总-下面代码的本质部分是列表和对象属性之间的绑定(在这里,为简单起见,它是一个String)。)

我尝试了各种事情。一种方法是在下面的Summary类的列表中使用addListener,但是我在侦听器回调中对Summary对象进行更新时遇到了奇怪的错误。经过一堆阅读后,我认为摘要字符串和列表之间的绑定更合适,但我不知道如何将绑定绑定到属性?

package com.example.demo.view

import javafx.beans.Observable
import javafx.beans.binding.StringBinding
import javafx.beans.property.SimpleIntegerProperty
import javafx.beans.property.SimpleListProperty
import javafx.beans.property.SimpleStringProperty
import javafx.collections.FXCollections
import tornadofx.View
import tornadofx.button
import tornadofx.label
import tornadofx.vbox

class Thing(x: Int) {
    val xProperty = SimpleIntegerProperty(x)
    val yProperty = SimpleStringProperty("xyz")
}

class Collection {
    private var things = FXCollections.observableList(mutableListOf<Thing>()) {
        arrayOf<Observable>(it.xProperty)
    }

    val thingsProperty = SimpleListProperty<Thing>(things)

    fun addThing(thing: Thing) {
        things.add(thing)
    }
}

class Summary(var collection: Collection) {
    val summaryBinding = object : StringBinding() {
        // The real code is more practical but
        // this is just a minimal example.
        override fun computeValue(): String {
            val sum = collection.thingsProperty.value
                .map { it.xProperty.value }
                .fold(0, { total, next -> total + next })
            return "There are $sum things."
        }
    }

    // How to make this property update when collection changes?
    val summaryProperty = SimpleStringProperty("There are ? things.")
}

class MainView : View() {
    val summary = Summary(Collection())

    override val root = vbox {
        label(summary.summaryProperty)
        button("Add Thing") {
            summary.collection.addThing(Thing(5))
        }
    }
}

1 个答案:

答案 0 :(得分:0)

请记住,我根据您的最小示例给出了此答案:

class Thing(x: Int) {
    val xProperty = SimpleIntegerProperty(x)
    var x by xProperty

    val yProperty = SimpleStringProperty("xyz")
    var y by yProperty
}


class MainView : View() {
    val things = FXCollections.observableList(mutableListOf<Thing>()) {
        arrayOf<Observable>(it.xProperty)
    }

    val thingsProperty = SimpleListProperty<Thing>(things)

    val totalBinding = integerBinding(listProperty) {
        value.map { it.x }.fold(0, { total, next -> total + next })
    }

    val phraseBinding = stringBinding(totalBinding) { "There are $value things." }

    override val root = vbox {
        label(phraseBinding)
        button("Add Thing") {
            action {
                list.add(Thing(5))
            }
        }
    }
}

我删除了您的其他课程,因为根据示例,我没有找到他们的理由。如果集合类比在实际项目中拥有list属性具有更多的功能,则只需将其添加回去即可。如果没有,则没有理由为列表提供自己的类。摘要类实际上只是两个绑定(如果不需要将总数与短语分开,则为一个绑定)。除非您打算在多个视图中使用它们,否则我也不认为需要给他们提供自己的课程。

我认为您最大的问题是您没有将按钮的动作包装在action {}中。因此,您的代码仅在初始化上添加了Thing(5)且未设置任何操作。

P.S。 var x by xProperty的东西只有在您import tornadofx.*使用该文件的情况下才能起作用。

相关问题