我尝试显示房屋的成本,该成本应根据房屋中的房间成本进行计算,并应显示在ListView中,但是当我更改房屋时,我无法让HouseListFragment正确显示更改房间的费用。
我试图通过Bindings.createIntegerBinding
和带有提取器的ObservableArray来实现这一点...
class House(name: String = "", rooms: MutableList<Room> = mutableListOf()) : NamedComponent(name)
{
val roomsProperty = SimpleListProperty<Room>(this, "rooms ", rooms.asObservable())
var rooms: ObservableList<Room> by roomsProperty
val costProperty = SimpleIntegerProperty(this, "cost", 0)
var cost by costProperty
var roomsCostChanged: ObservableList<IntegerProperty> = FXCollections.observableArrayList<IntegerProperty> { p -> arrayOf<Observable>(p) }
val totalProperty = Bindings.createIntegerBinding(
Callable { roomsCostChanged.stream().mapToInt { it.value }.sum() }, roomsCostChanged).toProperty()
init
{
updateRoomCostListenerList()
roomsProperty.onChange { _: ListChangeListener.Change<out Room> ->
run {
updateRoomCostListenerList()
}
}
}
private fun updateRoomCostListenerList()
{
roomsCostChanged.clear()
roomsProperty.forEach(Consumer { roomsCostChanged.add(it.costProperty) })
}
}
class HouseModel : ItemViewModel<House>()
{
val name = bind(House::nameProperty, autocommit = true)
val rooms = bind(House::roomsProperty, autocommit = true)
val cost = bind(House::totalProperty, autocommit = true)
}
class HouseFragment : ListCellFragment<House>()
{
private val controller by inject<QuotationController>()
private val house = HouseModel().bindTo(this)
override val root = vbox {
borderpane {
removeWhen { editingProperty }
top = hbox {
label(house.name) {
setId(Styles.contentLabel)
}
}
center = hbox {
label {
house.rooms.onChange {
text = "${it?.size} ${messages["rooms_in_this_house"]}"
}
}
}
right = label {
house.cost.onChange {
text = "${it?.get()} € total costs"
}
}
}
...
编辑:
通过更改init块来添加onChange侦听器和初始设置可以解决问题,最后不需要事件。对此,奥皮宁仍然表示赞赏...
init
{
roomsProperty.onChange { _: ObservableList<Room>? -> updateRoomCostListenerList() }
totalProperty.onChange { cost = it }
updateRoomCostListenerList()
cost = totalProperty.get()
}