Kotlin和TornadoFX:将一个可观察的属性绑定到一个集合函数?

我有一个Market ,其中包含一个名为m_updatesMarketUpdate对象m_updates 。 对于UI,我使用类型安全的构建器在tableview中创建列,如下所示:

 override val root = tableview<Market> { val sortedMarketList = SortedList<Market>(markets) sortedMarketList.comparatorProperty().bind(this.comparatorProperty()) items = sortedMarketList ... column("Strikes", Market::m_strikes) ... 

m_strikes属性只是一个由Market对象直接拥有的SimpleIntegerProperty。 但是,我需要能够建立像这样的列:

 ... column("Created At", Market::m_updates::first::m_time) ... ... column("Last Update", Market::m_updates::last::m_time) ... 

其中m_time是由MarketUpdate对象拥有的SimpleLongProperty。 当Market对象更新时,新的MarketUpdate对象被添加到m_updates集合的末尾。 这意味着绑定需要自动从一个对象转换到另一个对象,并且需要通知tableview并更新自己以反映新对象中的数据。 我认为通过上述集合的first()last()函数的绑定以一种非常简单的方式捕获了这个想法,但是它不会被编译。

有许多属性,如m_strikesm_time 。 我怎样才能达到这个优雅?

如果我理解了你的用例,你想要做的就是创建一个可观察的值,它表示给定Market对象中第一个和最后一个更新的时间属性。 为此,可以基于每个Market对象内的updates列表创建一个objectBinding ,然后提取第first()last()元素的timeProperty 。 在以下示例中,只要您在任何Market对象中增加更新列表,就会更新TableView。

请记住,该示例要求每个Market至少有一个更新。 如果这不是你的情况,确保相应地处理null。

 class Market { val updates = FXCollections.observableArrayList<MarketUpdate>() } class MarketUpdate { val timeProperty = SimpleObjectProperty(LocalDateTime.now()) } class MarketList : View("Markets") { val markets = FXCollections.observableArrayList<Market>() val data = SortedFilteredList<Market>(markets) override val root = borderpane { prefWidth = 500.0 center { tableview(markets) { column<Market, LocalDateTime>("Created at", { objectBinding(it.value.updates) { first() }.select { it!!.timeProperty } }) column<Market, LocalDateTime>("Last update", { objectBinding(it.value.updates) { last() }.select { it!!.timeProperty } }) } } bottom { toolbar { // Click to add an update to the first entry button("Add update").action { markets.first().updates.add(MarketUpdate()) } } } } init { // Add some test entries markets.addAll( Market().apply { updates.addAll(MarketUpdate(), MarketUpdate(), MarketUpdate()) }, Market().apply { updates.addAll(MarketUpdate(), MarketUpdate(), MarketUpdate()) }, Market().apply { updates.addAll(MarketUpdate(), MarketUpdate(), MarketUpdate()) }, Market().apply { updates.addAll(MarketUpdate(), MarketUpdate(), MarketUpdate()) } ) } } 

我已经使用SortedFilteredList来处理排序问题。 这里排序的原因是这些列实际上是由LocalDateTime值表示的。

导致的用户界面

我希望这给你一些想法:)