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

Aje*_*mar 5 java combobox javafx

我有一个ComboBox,列出了设置的值.我使用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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

Jam*_*s_D 8

默认情况下,大多数JavaFX控件在失去焦点TextField时不会"提交"一个值 - 因此,当用作较大控件内的编辑控件时,ComboBox除非用户按下,否则不会将值提交回父控件Enter.关于这个设计决定存在很多争议:然而,这是决定,如果我们要使用JavaFX,我们必须接受或者找到解决方法来获得我们想要的行为.

一个"快速而肮脏"的方法是挖掘文本字段并从中获取文本,如@ Ajeetkumar的答案:

selected.setText(emailComboBox.getEditor().getText());
Run Code Online (Sandbox Code Playgroud)

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

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

    emailComboBox.getEditor().focusedProperty().addListener((obs, wasFocused, isNowFocused) -> {
        if (! isNowFocused) {
            emailComboBox.setValue(emailComboBox.getEditor().getText());
        }
    });
Run Code Online (Sandbox Code Playgroud)

然后自然:

    b.setOnAction(e -> {
        selected.setText(emailComboBox.getValue());
    });
Run Code Online (Sandbox Code Playgroud)

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

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

    emailComboBox.getEditor().textProperty().addListener((obs, oldText, newText) -> {
        emailComboBox.setValue(newText);
    });
Run Code Online (Sandbox Code Playgroud)

请注意,如果您需要,使用此版本您可以完全省略按钮,只需将标签的文本直接绑定到组合框的值:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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