【问题标题】:How to assign a shortcut (key combination) to a JavaFx dialog如何为 JavaFx 对话框分配快捷键(组合键)
【发布时间】:2017-04-06 05:37:07
【问题描述】:

我还没有找到一种直接的方法来为 JavaFx 8 对话框中的按钮类型分配键盘快捷键。

例如:

dialog.dialogPane().getButtonTypes.addAll(ButtonType.OK, ButtonType.Cancel)

如何将 ESC 键分配给 ButtonType.Cancel ?

谢谢。

【问题讨论】:

  • Escape 不是默认分配给取消按钮的吗?
  • 举个例子
  • 在对话框窗格中,你不能只为你想按下按钮的任何键添加一个键监听器吗?
  • 是的,你可以催眠。但对话框 API 有点奇怪,因为您可以通过 lookupButton API 获取按钮实例等操作,在我习惯之前我发现这有点不寻常。因此下面的答案更长。

标签: javafx javafx-8


【解决方案1】:

您可以使用如下所示的加速器:

JavaFX 对话框在定义和使用按钮的方式上有点奇怪(而且复杂),因此添加加速器有点复杂,但仍然可以。下面的代码设置了一个加速器以在按下组合键时触发按钮操作,shortcut+f,其中快捷键将根据您的操作系统而变化(在 OS X 上,它是标记为“command”的键)。

// Create a custom button type:
ButtonType fishingButtonType = new ButtonType( "Go fishing", ButtonBar.ButtonData.OTHER);

dialog.getDialogPane().getButtonTypes().add(fishingButtonType);

// Set an accelerator and an action for the fishing button.
Button fishingButton = (Button) dialog.getDialogPane().lookupButton(fishingButtonType);
fishingButton.addEventFilter(ActionEvent.ACTION, ae -> {
    // linkware image: http://www.iconka.com
    dialog.setGraphic(new ImageView("http://icons.iconarchive.com/icons/iconka/meow/64/cat-fish-icon.png"));
    ae.consume();  // consume the action so that the dialog does not close when the button is pressed.
});
fishingButton.sceneProperty().addListener((observable, oldValue, newScene) -> {
    if (newScene != null) {
        newScene.getAccelerators().put(
                new KeyCodeCombination(KeyCode.F, KeyCombination.SHORTCUT_DOWN),
                fishingButton::fire
        );
    }
});

可执行示例代码

大部分代码都是从优秀的Makery JavaFX dialog tutorial 中提取的。在教程代码中添加了额外的代码来添加钓鱼按钮和触发它的加速器。

加速器触发前的对话框:

加速器触发后的对话框:

import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.image.ImageView;
import javafx.scene.input.*;
import javafx.scene.layout.*;
import javafx.stage.Stage;
import javafx.util.Pair;

import java.util.Optional;

public class LoginDialog extends Application {

    @Override 
    public void start(Stage stage) throws Exception {
        Button showDialogButton = new Button("Show Dialog");
        showDialogButton.setOnAction(event -> {
            showDialog();
        });

        StackPane layout = new StackPane(showDialogButton);
        layout.setPadding(new Insets(10));
        stage.setScene(new Scene(layout));

        stage.show();
    }

    private void showDialog() {
        // Create the custom dialog.
        Dialog<Pair<String, String>> dialog = new Dialog<>();
        dialog.setTitle("Login Dialog");
        dialog.setHeaderText("Look, a Custom Login Dialog");

        // Set the icon.
        // icon source: http://www.iconarchive.com/show/soft-scraps-icons-by-hopstarter/Lock-Lock-icon.html
        dialog.setGraphic(new ImageView("http://icons.iconarchive.com/icons/hopstarter/soft-scraps/64/Lock-Lock-icon.png"));

        // Set the button types.
        ButtonType loginButtonType = new ButtonType("Login", ButtonBar.ButtonData.OK_DONE);
        ButtonType fishingButtonType = new ButtonType( "Go fishing", ButtonBar.ButtonData.OTHER);
        dialog.getDialogPane().getButtonTypes().addAll(loginButtonType, fishingButtonType, ButtonType.CANCEL);

        // Create the username and password labels and fields.
        GridPane grid = new GridPane();
        grid.setHgap(10);
        grid.setVgap(10);
        grid.setPadding(new Insets(20, 150, 10, 10));

        TextField username = new TextField();
        username.setPromptText("Username");
        PasswordField password = new PasswordField();
        password.setPromptText("Password");

        grid.add(new Label("Username:"), 0, 0);
        grid.add(username, 1, 0);
        grid.add(new Label("Password:"), 0, 1);
        grid.add(password, 1, 1);

        // Enable/Disable login button depending on whether a username was entered.
        Node loginButton = dialog.getDialogPane().lookupButton(loginButtonType);
        loginButton.setDisable(true);

        // Set an accelerator and an action for the fishing button.
        Button fishingButton = (Button) dialog.getDialogPane().lookupButton(fishingButtonType);
        fishingButton.addEventFilter(ActionEvent.ACTION, ae -> {
            // linkware image: http://www.iconka.com
            dialog.setGraphic(new ImageView("http://icons.iconarchive.com/icons/iconka/meow/64/cat-fish-icon.png"));
            ae.consume();
        });
        fishingButton.sceneProperty().addListener((observable, oldValue, newScene) -> {
            if (newScene != null) {
                newScene.getAccelerators().put(
                        new KeyCodeCombination(KeyCode.F, KeyCombination.SHORTCUT_DOWN),
                        fishingButton::fire
                );
            }
        });

        // Do some validation (using the Java 8 lambda syntax).
        username.textProperty().addListener((observable, oldValue, newValue) -> {
            loginButton.setDisable(newValue.trim().isEmpty());
        });

        dialog.getDialogPane().setContent(grid);

        // Request focus on the username field by default.
        Platform.runLater(username::requestFocus);

        // Convert the result to a username-password-pair when the login button is clicked.
        dialog.setResultConverter(dialogButton -> {
            if (dialogButton == loginButtonType) {
                return new Pair<>(username.getText(), password.getText());
            }
            return null;
        });

        Optional<Pair<String, String>> result = dialog.showAndWait();

        result.ifPresent(usernamePassword -> {
            System.out.println("Username=" + usernamePassword.getKey() + ", Password=" + usernamePassword.getValue());
        });
    }

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-24
    • 2015-07-06
    • 1970-01-01
    相关资源
    最近更新 更多