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

标签 java javafx combobox javafx-11

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

对于 无法编辑 组合,即在按钮单元格中显示所选值(不在可编辑文本框中),如果新值为 ,则不显示任何值(按钮单元格可能被认为是“空”)未包含在组合的项目列表中 ,只有一个异常(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汤姆提供的效果很好。

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

相关文章:

java - 如何使数组处理更快?

java - 如何在文本字段JavaFx中直接消除字符,以使用户无法输入字符?

wpf - 将组合框绑定(bind)到数据网格的 MVVM 问题

c++ - 在Visual Studio MFC中,我可以在组合框中输入文本,但在代码中得到整数吗?

c# - WPF:带有重置项的组合框

java - 错误java.lang.NoClassDefFoundError:com.github.difflib.text.DiffRowGenerator $$ Lambda $ 0

c# - 在静态方法中使用 IoC 容器解析类型

用笔绘制自由式时,JavaFX 在 Canvas 上的性能下降

JavaFX TitledPane 更改的标题背景在鼠标输入时重置

java - 如何在Java中使用套接字输入/输出流捕获 “event”?