绑定一个 observable 属性 到一个集合函数?
Bind an observable property to a collection function?
我有一个 class Market
,其中包含一个名为 m_updates
的 MarketUpdate
个对象的集合。对于 UI,我使用类型安全的构建器在表视图中创建列,如下所示:
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 值表示。
我希望这能给你一些想法:)
我有一个 class Market
,其中包含一个名为 m_updates
的 MarketUpdate
个对象的集合。对于 UI,我使用类型安全的构建器在表视图中创建列,如下所示:
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 值表示。
我希望这能给你一些想法:)