How to assign a shortcut (key combination) to a Ja

2019-08-06 11:53发布

I have not found a direct way to assign a keyboard shortcut to a button type in a JavaFx 8 dialog.

For instance:

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

How can I assign the ESC key to ButtonType.Cancel ?

Thanks.

1条回答
乱世女痞
2楼-- · 2019-08-06 12:08

You can use an accelerator as demonstrated in:

JavaFX dialogs are a bit weird (and complicated) in the way they define and use buttons, so adding the accelerator gets a little convoluted, but is still possible. The code below sets up an accelerator to fire the button action when a key combination is pressed, shortcut+f, where the shortcut key will change depending on your OS (on OS X it is the key labeled "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
        );
    }
});

Executable Sample Code

Most of this code is just lifted from the excellent Makery JavaFX dialog tutorial. Additional code was added to the tutorial code to add the fishing button and the accelerator to trigger it.

Dialog before accelerator triggered: no fish

Dialog after accelerator triggered: go fish

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);
    }
}
查看更多
登录 后发表回答