在Javafx中输入关键事件不能正常工作?

问题描述 投票:2回答:4

我已经尝试了下面的代码,它可以正常使用鼠标事件,但是当我使用键事件,即任何按钮上的ENTER键,而不是显示结果。

Alert alert = new Alert(AlertType.CONFIRMATION);
alert.setTitle(null);
alert.setHeaderText(null);
alert.setGraphic(null);
alert.setContentText("Choose your option.");

ButtonType buttonTypeOne = new ButtonType("One");
ButtonType buttonTypeTwo = new ButtonType("Two");
ButtonType buttonTypeThree = new ButtonType("Three");

alert.getButtonTypes().setAll(buttonTypeOne, buttonTypeTwo, buttonTypeThree);

Optional<ButtonType> result = alert.showAndWait();
if (result.get() == buttonTypeOne) {
     System.out.println("One");
} else if (result.get() == buttonTypeTwo) {
     System.out.println("Two");
} else if (result.get() == buttonTypeThree) {
     System.out.println("Three");
}
javafx javafx-2 javafx-8
4个回答
8
投票

我不建议让所有按钮响应输入,因为这与大多数UI对话框的工作方式相反。

通常情况下,按空格键时会触发一个带焦点的按钮,而不是输入。然而,有一些特殊的按钮会在特定键上激活:一个default button将在输入时触发,而cancel button将在esc上触发。通常,对话框中只有一个特殊类型的按钮中的一个,因此无论当前哪个按钮具有焦点,都可以通过特殊的键盘加速器触发它们。

另外,不同的桌面OS系统在对话系统中具有关于默认和取消按钮的放置的不同标准。这是为了帮助用户在任何对话框中轻松找到这些特殊按钮。 JavaFX对话系统在内部实现了一些逻辑,用于在对话框中定位按钮,用户希望在不同的桌面操作系统中看到这些按钮。

假设您希望将示例中的按钮类型定义为默认按钮或取消按钮,并将其放置在适用于您的操作系统按钮的正确位置,然后您可以执行以下操作:

ButtonType buttonTypeTwo = new ButtonType(
    "Two",
    ButtonBar.ButtonData.OK_DONE
);
ButtonType buttonTypeThree = new ButtonType(
    "Three",
    ButtonBar.ButtonData.CANCEL_CLOSE
);

请注意,JavaFX系统已自动更改按钮的位置和一些颜色突出显示。当用户按下回车键时,“2”将激活,当用户按下esc时,“3”将激活。如果您在Windows或Linux上运行相同的代码,根据用于这些操作系统的任何按钮定位标准,可能按钮的位置不同。

enter image description here

如果您不希望JavaFX根据操作系统标准重新定位按钮,但您希望它们仍然响应enter和esc键,那么您可以查找按钮并直接修改按钮属性,如下所示:

Button buttonTwo = (Button) alert.getDialogPane().lookupButton(buttonTypeTwo);
buttonTwo.setDefaultButton(true);
Button buttonThree = (Button) alert.getDialogPane().lookupButton(buttonTypeThree);
buttonThree.setCancelButton(true);

adjusted button types

我建议让JavaFX正确定位特定类型的按钮,而不是像上面那样执行查找。

我还建议在JavaFX警报中至少设置一个CANCEL_CLOSE按钮或OK_DONE按钮,否则用户可能很难实际关闭警报,因为对话框可能无法响应用户期望的按键操作。


1
投票

我不知道这是不是一种太多的解决方法,但至少它是有效的:

 import javafx.event.EventHandler;
 import javafx.scene.control.Button;
 import javafx.scene.input.KeyCode;
 import javafx.scene.input.KeyEvent;

     [...]
ButtonType buttonTypeTwo = new ButtonType("Two");
ButtonType buttonTypeThree = new ButtonType("Three");

alert.getButtonTypes().setAll(buttonTypeOne, buttonTypeTwo, buttonTypeThree);

//Create a button for every ButtonType you add to your alert and give it a Eventhandler 
Button button1 = (Button) alert.getDialogPane().lookupButton(buttonTypeOne);
Button button2 = (Button) alert.getDialogPane().lookupButton(buttonTypeTwo);
Button button3 = (Button) alert.getDialogPane().lookupButton(buttonTypeThree);


button1.setOnKeyReleased(new EventHandler<KeyEvent>() {
    @Override
    public void handle(KeyEvent event) {
        if(event.getCode() == KeyCode.ENTER)
    alert.setResult(buttonTypeOne);     
    }
});
button2.setOnKeyReleased(new EventHandler<KeyEvent>() {
    @Override
    public void handle(KeyEvent event) {
        if(event.getCode() == KeyCode.ENTER)
    alert.setResult(buttonTypeTwo);     
    }
});
button3.setOnKeyReleased(new EventHandler<KeyEvent>() {
    @Override
    public void handle(KeyEvent event) {
        if(event.getCode() == KeyCode.ENTER)
    alert.setResult(buttonTypeThree);       
    }
});
 //go ahead with your code
Optional<ButtonType> result = alert.showAndWait();
[...]

您只需创建一些按钮并在警报上为它们分配实际按钮。在下一步中,你可以给每个按钮一个EventHandler,它只是(在这个例子中)检查 - 当任何键被释放时 - 如果键是ENTER并设置结果。

我想有更好的解决方案。但这是我目前最容易想到的方式。希望它能帮到你。


0
投票

我在这里如何解决它。它工作正常下面是我的确认警报功能。

public static boolean confirmAlert(String title, String msg){

        ButtonType buttonTypeYes = new ButtonType("Yes", ButtonBar.ButtonData.OK_DONE);
        ButtonType buttonTypeNo = new ButtonType("No",ButtonBar.ButtonData.CANCEL_CLOSE);

        Alert alert = new Alert(Alert.AlertType.NONE, msg,buttonTypeNo,buttonTypeYes);
        alert.setTitle(title);

        Button button1 = (Button) alert.getDialogPane().lookupButton(buttonTypeYes);
        button1.setDefaultButton(false); //***set default to false***

        Button button2 = (Button) alert.getDialogPane().lookupButton(buttonTypeNo);

        button1.setOnKeyReleased(event -> {
            if(event.getCode() == KeyCode.ENTER)
                alert.setResult(buttonTypeYes);
        });
        button2.setOnKeyReleased(event -> {
            if(event.getCode() == KeyCode.ENTER)
                alert.setResult(buttonTypeNo);
        });
        alert.showAndWait();
        return alert.getResult()==buttonTypeYes;
    }

0
投票

您不需要设置默认方法,在该按钮上要输入密钥

Alert confirmAlert = new Alert(Alert.AlertType.CONFIRMATION, "", ButtonType.YES, ButtonType.NO);
confirmAlert.setHeaderText("Are You Sure Want To Delete ?");
Button bt1 = (Button) confirmAlert.getDialogPane().lookupButton(ButtonType.YES);
Button bt2 = (Button) confirmAlert.getDialogPane().lookupButton(ButtonType.NO);
bt2.addEventHandler(KeyEvent.ANY,(event) -> {
    if(event.getCode() == KeyCode.ENTER){
    confirmAlert.setResult(ButtonType.NO);
      }
});
Optional <ButtonType> action = confirmAlert.showAndWait();
if(action.get() == ButtonType.NO){
          System.err.println("Action You Want");
}
© www.soinside.com 2019 - 2024. All rights reserved.