gpt4 book ai didi

JavaFX 11 不可编辑的 ComboBox 无法正确显示组合项列表之外的值

转载 作者:行者123 更新时间:2023-11-30 07:41:55 24 4
gpt4 key购买 nike

我在使用 JaxaFX 11 ComboBox 时遇到问题(似乎在 JavaFX 8 中它工作正常)。

对于 uneditable 组合,即在 buttoncell 中显示所选值(而不是在可编辑的文本框中),如果新值不是 not,则不显示任何值(buttoncell 可能被认为是“空的”)包含在组合的项目列表中,只有一个异常(exception):

如果先前的值为 null(例如,通过键盘在弹出列表中取消选择先前的非空值),则新的非空值将正确显示。

请参阅重现问题的简单代码。最初,组合值为 null。按下按钮以在项目列表之外设置一个值。显示正常。然后从弹出窗口中选择一些值。再次尝试按下按钮。现在组合保持为空,尽管组合值已更改。

import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.collections.FXCollections;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.TextField;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class ComboTest extends Application {
private ComboBox<String> testCombo;

@Override public void start(Stage primaryStage) {
Button btn = new Button("Set test value outside list");
btn.setOnAction(e -> {
testCombo.setValue("test value outside list");
});

testCombo = new ComboBox<>(FXCollections.observableArrayList(
"Option 1", "Option 2", "Option 3"
));
testCombo.setPromptText("null now!");

TextField valueTextField = new TextField();
testCombo.valueProperty().addListener((ob, ov, nv) -> {
valueTextField.setText("combo value: " + nv);
});

VBox root = new VBox(5);
root.setPadding(new Insets(5));
root.getChildren().addAll(btn, testCombo, valueTextField);

Scene scene = new Scene(root, 300, 250);

primaryStage.setTitle("Test Combo");
primaryStage.setScene(scene);
primaryStage.show();
}

public static void main(String[] args) {
launch(args);
}
}

我错过了什么吗?我找不到任何解决方法。我试图调试,但找不到答案。似乎首先设置了正确的文本,但随后又被删除了。

(JDK 11.0.2、JavaFX 11.0.2、Netbeans 10)

最佳答案

对我来说看起来像是一个错误:由于某种原因,displayNode(即 buttonCell 的内容)在设置未包含的值时未更新,同时选择了包含的值。仅通过其在 ComboBoxBaseSkin 上的公共(public) api 访问 displayNode 即可触发正确的设置。

要查看它的更新,请将以下行添加到您的示例中,并在未包含的值未显示后单击该按钮:

Button display = new Button("getDisplayNode");
display.setOnAction(e -> {
((ComboBoxBaseSkin) testCombo.getSkin()).getDisplayNode();
});

为了解决这个问题,我们可以扩展组合的皮肤并在每个布局 channel 中强制更新:

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);
}

}

用法:

testCombo = new ComboBox<>(FXCollections.observableArrayList("Option 1", "Option 2", "Option 3")) {
@Override
protected Skin<?> createDefaultSkin() {
return new MyComboBoxSkin<>(this);
}
};

注意:皮肤实现大量使用了多个 boolean 脏标志,在这种特殊情况下它们似乎破坏性地相互作用(不幸的是,不明白到底是怎么回事)。使用 Platform.runlater 延迟访问似乎可行。


更新

经过进一步挖掘,它看起来像是一个 regressionlazy-dirty介绍(不是我的措辞,虽然喜欢它 :) 修复。 custom cell implementation Tom 提供的效果很好。

关于JavaFX 11 不可编辑的 ComboBox 无法正确显示组合项列表之外的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55378762/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com