Java 调用组合框';s输入键/操作事件处理程序,而不考虑值属性的更改

Java 调用组合框';s输入键/操作事件处理程序,而不考虑值属性的更改,java,combobox,javafx,javafx-8,Java,Combobox,Javafx,Javafx 8,对于可编辑的,是否有任何方法可以让ENTER键事件或操作事件处理程序发生,而不管组合框的value属性是否已更改? 我基本上希望在按下ENTER键时,在组合框的文本字段中有与在文本字段中相同的行为 我试过的 我最初的想法是简单地使用组合框;然而,根据it的文件: ComboBox操作,每当更改ComboBox value属性时都会调用该操作。这可能是由于当用户在弹出列表或对话框中选择一个项目时,或者在可编辑组合框的情况下,当用户提供自己的输入(通过文本字段或其他输入机制)时,通过编程方式更改了v

对于可编辑的,是否有任何方法可以让ENTER键事件或操作事件处理程序发生,而不管
组合框的value属性是否已更改?

我基本上希望在按下ENTER键时,在
组合框
文本字段
中有与在
文本字段
中相同的行为

我试过的 我最初的想法是简单地使用
组合框
;然而,根据it的文件:

ComboBox操作,每当更改ComboBox value属性时都会调用该操作。这可能是由于当用户在弹出列表或对话框中选择一个项目时,或者在可编辑组合框的情况下,当用户提供自己的输入(通过文本字段或其他输入机制)时,通过编程方式更改了value属性

因此,通过使用
setOnAction
,事件处理程序仅在以下情况下发生:

  • “值”属性通过更改从中选择的内容进行更改 下拉或
  • value属性通过用户输入进行更改(即:不会发生更改) 如果用户未键入任何内容并按ENTER键,则不会发生 如果用户在事件处理程序运行后不更改其输入 一次,然后按ENTER)
  • 此外,在
    组合框
    文本字段
    上使用
    设置操作
    ,或使用都不能达到所需的行为

    以下是一个SSCCE,用于演示:

    import javafx.application.Application;
    import javafx.collections.FXCollections;
    import javafx.scene.Scene;
    import javafx.scene.control.ComboBox;
    import javafx.scene.control.TextField;
    import javafx.scene.input.KeyCode;
    import javafx.scene.layout.HBox;
    import javafx.stage.Stage;
    
    public class Example extends Application {
    
        @Override
        public void start(Stage primaryStage) {
            ComboBox<String> comboBox =
                new ComboBox<String>(
                        FXCollections.observableArrayList("XYZ", "ABC"));
            comboBox.setEditable(true);
            comboBox.setValue(comboBox.getValue());
            comboBox.setOnAction((event) -> System.out
                    .println("occurs on selection changes or text changes and ENTER key"));
            comboBox.getEditor().setOnAction(
                    (event) -> System.out.println("this never happens"));
            comboBox.getEditor().setOnKeyPressed((keyEvent) -> {
                if (keyEvent.getCode() == KeyCode.ENTER)
                    System.out.println("this never happens either");
            });
    
            TextField tf = new TextField();
            tf.setOnAction((event) -> System.out.println("always happens on ENTER"));
    
            HBox hbox = new HBox(comboBox, tf);
    
            Scene scene = new Scene(hbox);
    
            primaryStage.setScene(scene);
            primaryStage.show();
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    }
    
    导入javafx.application.application;
    导入javafx.collections.FXCollections;
    导入javafx.scene.scene;
    导入javafx.scene.control.ComboBox;
    导入javafx.scene.control.TextField;
    导入javafx.scene.input.KeyCode;
    导入javafx.scene.layout.HBox;
    导入javafx.stage.stage;
    公共类示例扩展了应用程序{
    @凌驾
    公共无效开始(阶段primaryStage){
    组合框组合框=
    新组合框(
    FXCollections.observableArrayList(“XYZ”、“ABC”);
    comboBox.setEditable(真);
    comboBox.setValue(comboBox.getValue());
    comboBox.setOnAction((事件)->System.out
    .println(“在选择更改或文本更改时发生并输入键”);
    comboBox.getEditor().setOnAction(
    (事件)->System.out.println(“这永远不会发生”);
    comboBox.getEditor().setOnKeyPressed((keyEvent)->{
    if(keyEvent.getCode()==KeyCode.ENTER)
    System.out.println(“这种情况也不会发生”);
    });
    TextField tf=新的TextField();
    tf.setOnAction((事件)->System.out.println(“总是在回车时发生”);
    HBox HBox=新的HBox(组合框,tf);
    场景=新场景(hbox);
    初级阶段。场景(场景);
    primaryStage.show();
    }
    公共静态void main(字符串[]args){
    发射(args);
    }
    }
    
    作为了解事件处理工作原理的一般方法,您始终可以使用Event.ANY添加一个eventfilter,并查看发生了什么,例如:

    comboBox.getEditor().addEventFilter(Event.ANY, e -> System.out.println(e));
    
    该事件被触发,如控制台中所示。因此,您需要为密钥代码添加一个筛选器,如下所示:

    comboBox.getEditor().addEventFilter(KeyEvent.KEY_PRESSED, e -> {
    
        if (e.getCode() == KeyCode.ENTER) {
            System.out.println( "Enter pressed");
        }
    
    });
    
    关于您的问题,您可以查看ComboBoxListViewSkin,从中可以看到事件已被使用

    private EventHandler<KeyEvent> textFieldKeyEventHandler = event -> {
        if (textField == null || ! getSkinnable().isEditable()) return;
        handleKeyEvent(event, true);
    };
    
    ...
    
    private void handleKeyEvent(KeyEvent ke, boolean doConsume) {
        // When the user hits the enter or F4 keys, we respond before
        // ever giving the event to the TextField.
        if (ke.getCode() == KeyCode.ENTER) {
            setTextFromTextFieldIntoComboBoxValue();
    
            if (doConsume) ke.consume();
        } 
        ...
    }
    
    private EventHandler textFieldKeyEventHandler=event->{
    if(textField==null | |!getSkinnable().isEditable())返回;
    handleKeyEvent(事件,真);
    };
    ...
    私有void handleKeyEvent(KeyEvent ke,布尔文档消费){
    //当用户点击回车键或F4键时,我们会在之前做出响应
    //将事件提供给文本字段。
    if(ke.getCode()==KeyCode.ENTER){
    将xtFromTextField设置为ComboboxValue();
    if(doConsume)ke.consume();
    } 
    ...
    }
    
    简而言之:使用EventFilter而不是EventHandler

    您可以在文档中阅读更多关于这方面的内容