我正在尝试使用纯字段将JavaFX代码(例如,我的自定义多列ComboBox)重构为要尝试学习的属性(可观察对象)。
在我的实现中,字段与某种程度上相关-例如更改一个字段会导致将其他字段重置为某些值:
private MyModel model; // data (in rows and cols) for my multicolumn combo
private int valueColumn; // column index to get the combo value from
private int displayColumn; // column index to get the combo text from
// model setter
// - setting a new model leads to clearing valueColumn and displayColumn to
// (default) 0 (values used for previous model are not relevant)
public void setModel(MyModel model) {
this.model = model;
valueColumn = 0;
displayColumn = 0;
reactToComboChange();
}
public setValueColumn(int valueColumn) {
this.valueColumn = valueColumn;
reactToComboChange();}
在这种简单的实施方式中(仅作为示例),可以确保字段在任何反应开始之前立即更改为合法状态-reactToComboChange()
当重构为可观察对象时,我使用变更侦听器,而不是在字段设置器中调用“反应”方法。
我的问题是,监听器代码是在每个属性更改后运行的,即,在相关属性的“组合”可能为“无效”的情况下(并非所有属性都设置为合法目标)值)-例如已经设置了新模型,在modelProperty侦听器中更改了valueColumnProperty,并立即通知其列表器,但是第三个属性displayColumnProperty仍未更改(重置为0),等等。
modelProperty().addListener((ob, ov, nv) -> {
setValueColumn(0);
setDisplayColumn(0);
reactToComboChange();
});
valueColumnProperty().addListener((ob, ov, nv) -> {
reactToComboChange();
});
...
这只是一个理论上的例子。我的问题很笼统:是否有办法在通知所有侦听器之前立即更改更多相关属性?(我想答案是否定的)。 是否存在一些解决此类情况的标准策略?我应该学习和使用相关属性的一些标准模式吗?我不知道...
我的实际解决方案是使用布尔变量isChangingModelNow
(在modelPropertyLister的开头设置为true,在此侦听器的末尾设置为false),以防止由于更改而通知的valueColumn和displayColumn的侦听器中有任何操作是在modelProperty侦听器中完成的,但这是一个hack ...