【问题标题】:How to reset ComboBox and display PromptText?如何重置 ComboBox 并显示 PromptText?
【发布时间】:2018-11-07 05:19:51
【问题描述】:

注意: 我正在扩展重复的问题here,因为它不包含 MCVE。我发现的其他几个类似问题也不包括有效答案。

在清除选择后,我无法找到让ComboBox 显示PromptText 的方法。

这是 MCVE:

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception {

        final VBox root = new VBox(10);
        root.setAlignment(Pos.TOP_CENTER);
        root.setPadding(new Insets(10));

        final ComboBox<String> cboSelection = new ComboBox<>();
        final Button btnClear = new Button("Clear");

        // Set ComboBox selections
        final ObservableList<String> subjectsList = FXCollections.observableArrayList();
        subjectsList.addAll("Software", "Math", "Physics");

        // Setup the Subject selection
        cboSelection.setPromptText("Select Subject");
        cboSelection.setItems(subjectsList);

        // Set action for "Clear" button
        btnClear.setOnAction(e -> {
            cboSelection.setValue(null);
        });

        root.getChildren().addAll(cboSelection, btnClear);

        primaryStage.setTitle("ComboBox Demo");
        primaryStage.setScene(new Scene(root, 200, 100));
        primaryStage.show();


    }


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

}

单击“清除”按钮会将选中的值设置为null,并清除选中的ComboBox,但提示文本不再显示。这似乎不是正常的预期行为。

我在按钮的onAction 中尝试了clearSelection()setPromptText(),但似乎无法恢复提示文本。

【问题讨论】:

    标签: java javafx combobox


    【解决方案1】:

    根据documentation,这里根本不应该显示提示文字:

    提示文本并非在所有情况下都显示,它依赖于 ComboBoxBase 的子类来明确提示文本何时显示。例如,在大多数情况下,当组合框不可编辑时,提示文本永远不会显示(也就是说,提示文本仅在用户通过文本输入允许输入时显示)。

    如果您想在选择为空时看到一些提示文本(并且您没有可编辑的组合框),请在组合框上使用自定义 buttonCell

        cboSelection.setPromptText("Select Subject");
        cboSelection.setButtonCell(new ListCell<String>() {
            @Override
            protected void updateItem(String item, boolean empty) {
                super.updateItem(item, empty) ;
                if (empty || item == null) {
                    setText("Select Subject");
                } else {
                    setText(item);
                }
            }
        });
    

    请注意,您似乎需要设置提示文本,就像问题中的代码一样,以便让文本最初出现。我认为这是因为相同的错误(我猜测库代码最初错误地将按钮单元格的文本设置为提示文本;如果未设置提示文本,则文本设置为null,显然按钮单元格的更新方法被调用之后)。

    您显然可以通过创建ListCell 的命名子类来使其可重用:

    public class PromptButtonCell<T> extends ListCell<T> {
    
        private final StringProperty promptText = new SimpleStringProperty();
    
        public PromptButtonCell(String promptText) {
            this.promptText.addListener((obs, oldText, newText) -> {
                if (isEmpty() || getItem() == null) {
                    setText(newText);
                }
            });
            setPromptText(promptText);
        }
    
        public StringProperty promptTextProperty() {
            return promptText ;
        }
    
        public final String getPromptText() {
            return promptTextProperty().get();
        }
    
        public final void setPromptText(String promptText) {
            promptTextProperty().set(promptText);
        }
    
        @Override
        protected void updateItem(T item, boolean empty) {
            super.updateItem(item, empty);
            if (empty || item == null) {
                setText(getPromptText());
            } else {
                setText(item);
            }
        }
    }
    

    然后只是

    cboSelection.setButtonCell("Select Subject");
    cboSelection.setButtonCell(new PromptButtonCell<>("Select Subject"));
    

    【讨论】:

    • 子类的构造函数中empty的第一个值是从哪里来的?示例类将无法编译。另外仅供参考,添加侦听器时,您缺少 this 参考的 this 关键字。
    • 顺便说一句,我将示例类的构造函数更改为仅设置promptText,省略了侦听器,并且组合框的功能按预期工作。
    • @Zephyr 对不起,应该是方法调用;见更新。 (我测试了第一个版本,但没有测试可重复使用的版本。)this 是可选的。仅当您稍后更改提示文本时才需要侦听器,而选择为空。
    • 啊,这样更好。尽管我仍然认为this 是必需的,因为您也将promptText 作为传递给构造函数的字符串的名称。话虽如此,这个答案对于手头的问题很有效,我不知道文档对不可编辑的组合框上的提示文本说了什么,所以谢谢你。
    猜你喜欢
    • 2015-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-09
    • 1970-01-01
    相关资源
    最近更新 更多