如何在 JavaFx 的可编辑 ComboBox 中获取输入值?

Posted

技术标签:

【中文标题】如何在 JavaFx 的可编辑 ComboBox 中获取输入值?【英文标题】:How to get entered value in editable ComboBox in JavaFx? 【发布时间】:2016-10-21 18:24:28 【问题描述】:

我有一个组合框,其中列出了设置的值。我已使用 setEditable(true) 方法使其可编辑,但如何获取用户输入的值?我尝试了 getSelectionModel().getSelectedItem() 和 getValue() 方法,但没有成功。

这是代码。

public class Comparator extends Application 

    @Override
      public void start(Stage stage) 
        stage.setTitle("ComboBoxSample");
        Scene scene = new Scene(new Group(), 450, 250);

        ComboBox<String> emailComboBox = new ComboBox<>();
        emailComboBox.getItems().addAll("A","B","C","D","E");

        emailComboBox.setEditable(true);        

        Button b = new Button("get text");

        GridPane grid = new GridPane();
        grid.setVgap(4);
        grid.setHgap(10);
        grid.setPadding(new Insets(5, 5, 5, 5));
        Label to = new Label("To: ");
        Label selected = new Label();
        grid.add(to, 0, 0);
        grid.add(emailComboBox, 1, 0);
        grid.add(b, 2, 0);
        grid.add(selected, 3, 0);

        b.setOnAction(e -> 
            selected.setText(emailComboBox.????);
        );

        Group root = (Group) scene.getRoot();
        root.getChildren().add(grid);
        stage.setScene(scene);
        stage.show();
      

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

我实际上想要获取新输入的值。 PS:如果以防万一,只是为了避免混淆。我可以输入列表中不存在的任何字符串。这将是输入的新值。

【问题讨论】:

“没有成功”是什么意思? emailComboBox.getValue() 应该可以正常工作。会发生什么? 当我在文本框中输入并单击按钮时,它什么也不显示。 您是否在输入值后按回车键来提交该值? getValue() 在按下回车后起作用。这不是我要找的。 getEditor().getText() 效果很好。 【参考方案1】:

默认情况下,大多数 JavaFX 控件在失去焦点时不会“提交”值 - 所以TextFields,当在较大的控件(例如 ComboBox)中用作编辑控件时,不要将值提交回除非用户按下 Enter,否则父控件。关于这个设计决定存在很多争议:然而,这是做出的决定,如果我们要使用 JavaFX,我们必须要么接受它,要么想办法解决它以获得我们想要的行为。

一种“快速而肮脏”的方法是挖掘文本字段并从中获取文本,如@Ajeetkumar 的回答:

selected.setText(emailComboBox.getEditor().getText());

这种方法的问题在于它使应用程序处于不一致的状态:标签中显示给用户的值不是组合框模型中保存的值:换句话说,emailComboBox.getValue() 返回一个不同的将值设置为标签中显示的值(因为文本字段中的值从未提交给组合框)。在某些时候,您的应用程序需要处理显示的数据,而程序员(或团队的其他成员)查找数据的自然位置是在组合框的模型中:即他们希望数据位于 @987654326 @。更好的方法是确保组合框的值在您需要时更新,然后只需使用预期的emailComboBox.getValue() 来获取数据。

例如,您可以在文本字段失去焦点时更新值:

    emailComboBox.getEditor().focusedProperty().addListener((obs, wasFocused, isNowFocused) -> 
        if (! isNowFocused) 
            emailComboBox.setValue(emailComboBox.getEditor().getText());
        
    );

然后是自然:

    b.setOnAction(e -> 
        selected.setText(emailComboBox.getValue());
    );

使用这种方法,应用程序始终处于一致状态:即标签显示组合框的值,这比直接从文本字段设置标签更不可能在以后引起错误。

另一种变化是在编辑器中的文本更改后立即更新组合框值:

    emailComboBox.getEditor().textProperty().addListener((obs, oldText, newText) -> 
        emailComboBox.setValue(newText);
    );

请注意,如果您愿意,使用此版本实际上可以完全放弃按钮,只需将标签的文本直接绑定到组合框的值:

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;

public class Comparator extends Application 

    @Override
      public void start(Stage stage) 
        stage.setTitle("ComboBoxSample");
        Scene scene = new Scene(new Group(), 450, 250);

        ComboBox<String> emailComboBox = new ComboBox<>();
        emailComboBox.getItems().addAll("A","B","C","D","E");

        emailComboBox.setEditable(true);        

        emailComboBox.getEditor().textProperty().addListener((obs, oldText, newText) -> 
            emailComboBox.setValue(newText);
        );


        GridPane grid = new GridPane();
        grid.setVgap(4);
        grid.setHgap(10);
        grid.setPadding(new Insets(5, 5, 5, 5));
        Label to = new Label("To: ");
        Label selected = new Label();
        grid.add(to, 0, 0);
        grid.add(emailComboBox, 1, 0);
        grid.add(selected, 2, 0);

        selected.textProperty().bind(emailComboBox.valueProperty());

        Group root = (Group) scene.getRoot();
        root.getChildren().add(grid);
        stage.setScene(scene);
        stage.show();
      

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

强烈建议保持数据的完整性以保持应用程序的一致性并减少以后引入错误的可能性,因此强烈建议更新组合框的 value 属性以包含您要表示的值,然后引用该值。用作编辑器的文本字段实际上是组合框的一个实现细节,只应用于修改组合框编辑过程的行为:在本例中,它用于修改更新行为 - 您还可以在它等。它不应该用作模型的代理,因为这会让以后的生活变得困难。

【讨论】:

@Ajeetkumar 自 fx9 以来,commit-on-focuslost 是所有可编辑输入组件(combo、spinner、datePicker)的默认行为 - 请参阅 bugs.openjdk.java.net/browse/JDK-8150946 对于 commit-on-typing,您仍然需要编辑器的 textProperty 上的 changeListener,按照 James 的建议提交更改【参考方案2】:

我得到了答案。

emailComboBox.getEditor().getText()

我们在可编辑 ComboBox 中键入的文本字段称为 ComboBox 的 编辑器。它是一个普通的 TextField 对象。要访问该对象,您需要使用方法 ComboBox.getEditor()。这样就可以使用TextField类的方法了。

【讨论】:

不知道为什么这被否决了。这对我有用。没有其他答案对我有用。 这可能是个坏主意。如果编辑器没有提交该值,那么您将处于标签中的文本与组合框保存的值不同的情况。由于您的目标是使标签的文本等于组合框的值,这实质上意味着您的应用程序处于不一致的状态。这是否会导致实际问题取决于您的应用程序正在做什么以及您的实际需求,但即使当前的需求不会导致这成为问题,您也可以稍后添加功能并发现这会导致问题。 您提到的情况实际上发生在 getValue() 上。如果我使用 getValue() 我们需要按 enter 来提交值。而 getEditor.getText() 不需要输入键,即使我只是键入并单击按钮,它也可以工作。你试过吗? 我试过了。它仅在非常狭义的意义上“起作用”,即它将标签更新为您想要的值。问题是它没有更新组合框的value 属性,因此您的应用程序现在处于不一致的状态。关键是您将要在某个时候处理数据(发送到数据库,发送电子邮件,做某事),当您这样做时,标签不是您期望找到数据的地方 - 您(或您团队中的另一位程序员)会期望它在组合框的模型中,即在value 属性中。您应该确保更新 value【参考方案3】:

这将在您更改编辑器值时更改列表

pluginConfig.getEditor().textProperty().addListener((obs, oldText, newText) -> 
        if (pluginConfig.getSelectionModel().getSelectedIndex() >= 0)
            pluginConfig.getItems().set(pluginConfig.getSelectionModel().getSelectedIndex(),newText);
    );

【讨论】:

【参考方案4】:

您可以使用以下代码行获取ComboBox中的选定值,并设置在Label上:

selected.setText(emailComboBox.getValue());

由于您使用的是字符串,您还应该将ComboBox的参数化类型设置如下:

ComboBox<String> emailComboBox = new ComboBox<>();

【讨论】:

您是否按照建议修复了ComboBox 的类型?如果您不这样做,它将无法正常工作。 使用 getValue() 需要我按回车键来提交值。然后它在我单击按钮后起作用。但这不是我想要的。【参考方案5】:

试试这个:

String surName=cmbSurName.getSelectionModel().getSelectedItem().toString();
System.out.println(surName);

【讨论】:

以上是关于如何在 JavaFx 的可编辑 ComboBox 中获取输入值?的主要内容,如果未能解决你的问题,请参考以下文章

如何以编程方式在 JavaFX ComboBox 中设置字符串值

如何在 JavaFX 2 中编辑 ComboBoxTableCell 的默认渲染行为?

如何修复 javafx 中的渲染错误(ComboBox、ListView)

如何将图像工具提示添加到 JavaFX 中的 ComboBox 项?

如何检查是不是在 JavaFX ComboBox 中选择了任何项目

在 JavaFX 中管理 ComboBox 项