Kotlin和TornadoFX:将一个可观察的属性绑定到一个集合函数?
我有一个Market
,其中包含一个名为m_updates
的MarketUpdate
对象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_strikes
和m_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值表示的。
我希望这给你一些想法:)