对我来说看起来像一个错误:由于某种原因,在选择包含的值时,在设置不包含的值时,displayNode(即buttonCell的内容)不会更新。仅通过 ComboBoxBaseSkin 上的公共 api 访问 displayNode 即可触发正确的设置。
要查看它的更新,请将以下行添加到您的示例中,然后在不显示未包含的值后单击该按钮:
Button display = new Button("getDisplayNode");
display.setOnAction(e -> {
((ComboBoxBaseSkin) testCombo.getSkin()).getDisplayNode();
});
为了解决这个问题,我们可以扩展组合的皮肤并在每个布局过程中强制更新:
public static class MyComboBoxSkin<T> extends ComboBoxListViewSkin<T> {
public MyComboBoxSkin(ComboBox<T> control) {
super(control);
}
@Override
protected void layoutChildren(double x, double y, double w, double h) {
super.layoutChildren(x, y, w, h);
// must be wrapped inside a runlater, either before or after calling super
Platform.runLater(this::getDisplayNode);
}
}
usage:
testCombo = new ComboBox<>(FXCollections.observableArrayList("Option 1", "Option 2", "Option 3")) {
@Override
protected Skin<?> createDefaultSkin() {
return new MyComboBoxSkin<>(this);
}
};
注意:皮肤实现大量使用了多个布尔脏标志,在这种特殊情况下它们似乎会产生破坏性的交互(不幸的是,不明白到底是如何交互的)。使用 Platform.runlater 延迟访问似乎有效。
Update
经过进一步挖掘,它看起来像是回归由一个介绍懒惰-肮脏(不是我的措辞,尽管喜欢它:)修复。这自定义单元实现汤姆提供的效果很好。