How to assign a shortcut (key combination) to a JavaFx dialog

非 Y 不嫁゛ 提交于 2019-12-11 04:28:29

问题


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:


You can use an accelerator as demonstrated in:

  • Using JavaFX 2.2 Mnemonic (and accelerators)

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:

Dialog after accelerator triggered:

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);
    }
}


来源:https://stackoverflow.com/questions/43238705/how-to-assign-a-shortcut-key-combination-to-a-javafx-dialog

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!