2012-10-03 36 views
8

Estoy tratando de hacer funcionar JavaFX Mnemonic. Tengo un botón en la escena y lo que quiero lograr es disparar este evento de botón presionando Ctrl + S. Aquí es una sceleton código: mnemonicParsingUsando JavaFX 2.2 Mnemónico (y aceleradores)

@FXML 
public Button btnFirst; 

btnFirst.getScene().addMnemonic(new Mnemonic(btnFirst, 
      new KeyCodeCombination(KeyCode.S, KeyCombination.CONTROL_DOWN))); 

de Button es falsa. (Bueno, al intentar hacer esto, intenté establecerlo en verdadero, pero sin resultado). La documentación de JavaFX establece que cuando un Mnemónico se registra en una Escena y KeyCombination no llega a la Escena, entonces el Nodo de destino recibirá un ActionEvent. Pero esto no funciona, probablemente, estoy haciendo mal ...

Puedo usar el mnemónico del botón estándar (estableciendo mnemonicParsing en verdadero y prefijo la letra 'F' por el carácter de subrayado). Pero de esta manera el usuario tiene que usar la tecla Alt, que trae un comportamiento extraño en los navegadores con la barra de menú (si la aplicación está integrada en la página web que el menú del navegador activado después del evento del botón de disparo presionando Alt + S). Además, la forma estándar hace que sea imposible hacer accesos directos como Ctrl + Shift + F3 y así sucesivamente.

Entonces, si hay alguna forma de hacerlo funcionar?

Respuesta

20

Para su caso de uso, creo que realmente desea utilizar un acelerador en lugar de un mnemónico.

button.getScene().getAccelerators().put(
    new KeyCodeCombination(KeyCode.S, KeyCombination.SHORTCUT_DOWN), 
    new Runnable() { 
    @Override public void run() { 
     button.fire(); 
    } 
    } 
); 

En la mayoría de los casos se recomienda que utilice KeyCombination.SHORTCUT_DOWN como el especificador de modificador, como en el código de seguridad. Una buena explicación de esto está en la documentación KeyCombination:

El modificador de acceso directo se utiliza para representar la tecla de modificación que es de uso común en los atajos de teclado en la plataforma anfitrión. Esto es para el control de ejemplo en Windows y meta (tecla de comando) en Mac. Mediante el uso de , los desarrolladores de modificador de tecla de método abreviado pueden crear accesos directos independientes de la plataforma. Por lo tanto, la combinación de teclas "Acceso directo + C" se maneja internamente como "Ctrl + C" en Windows y "Meta + C" en Mac.

Si quería específicamente código sólo para manejar la combinación de teclas CTRL + S, que puede usar:

new KeyCodeCombination(KeyCode.S, KeyCombination.CONTROL_DOWN) 

Aquí es un ejemplo ejecutable: salida

import javafx.animation.*; 
import javafx.application.Application; 
import javafx.event.*; 
import javafx.geometry.Pos; 
import javafx.scene.Scene; 
import javafx.scene.control.*; 
import javafx.scene.image.*; 
import javafx.scene.input.*; 
import javafx.scene.layout.VBox; 
import javafx.stage.Stage; 
import javafx.util.Duration; 

public class SaveMe extends Application { 
    @Override public void start(final Stage stage) throws Exception { 
    final Label response = new Label(); 
    final ImageView imageView = new ImageView(
     new Image("http://icons.iconarchive.com/icons/gianni-polito/colobrush/128/software-emule-icon.png") 
    ); 
    final Button button = new Button("Save Me", imageView); 
    button.setStyle("-fx-base: burlywood;"); 
    button.setContentDisplay(ContentDisplay.TOP); 
    displayFlashMessageOnAction(button, response, "You have been saved!"); 

    layoutScene(button, response, stage); 
    stage.show(); 

    setSaveAccelerator(button); 
    } 

    // sets the save accelerator for a button to the Ctrl+S key combination. 
    private void setSaveAccelerator(final Button button) { 
    Scene scene = button.getScene(); 
    if (scene == null) { 
     throw new IllegalArgumentException("setSaveAccelerator must be called when a button is attached to a scene"); 
    } 

    scene.getAccelerators().put(
     new KeyCodeCombination(KeyCode.S, KeyCombination.SHORTCUT_DOWN), 
     new Runnable() { 
     @Override public void run() { 
      fireButton(button); 
     } 
     } 
    ); 
    } 

    // fires a button from code, providing visual feedback that the button is firing. 
    private void fireButton(final Button button) { 
    button.arm(); 
    PauseTransition pt = new PauseTransition(Duration.millis(300)); 
    pt.setOnFinished(new EventHandler<ActionEvent>() { 
     @Override public void handle(ActionEvent event) { 
     button.fire(); 
     button.disarm(); 
     } 
    }); 
    pt.play(); 
    } 

    // displays a temporary message in a label when a button is pressed, 
    // and gradually fades the label away after the message has been displayed. 
    private void displayFlashMessageOnAction(final Button button, final Label label, final String message) { 
    final FadeTransition ft = new FadeTransition(Duration.seconds(3), label); 
    ft.setInterpolator(Interpolator.EASE_BOTH); 
    ft.setFromValue(1); 
    ft.setToValue(0); 
    button.setOnAction(new EventHandler<ActionEvent>() { 
     @Override public void handle(ActionEvent event) { 
     label.setText(message); 
     label.setStyle("-fx-text-fill: forestgreen;"); 
     ft.playFromStart(); 
     } 
    }); 
    } 

    private void layoutScene(final Button button, final Label response, final Stage stage) { 
    final VBox layout = new VBox(10); 
    layout.setPrefWidth(300); 
    layout.setAlignment(Pos.CENTER); 
    layout.getChildren().addAll(button, response); 
    layout.setStyle("-fx-background-color: cornsilk; -fx-padding: 20; -fx-font-size: 20;"); 
    stage.setScene(new Scene(layout)); 
    } 

    public static void main(String[] args) { launch(args); } 
} 
// icon license: (creative commons with attribution) http://creativecommons.org/licenses/by-nc-nd/3.0/ 
// icon artist attribution page: (eponas-deeway) http://eponas-deeway.deviantart.com/gallery/#/d1s7uih 

de la muestra:

Sample program output

+0

jewelsea, gracias yo tú Tienes toda la razón, los aceleradores son mi caso de uso. Pensé equivocadamente que los aceleradores deben estar conectados a los elementos del menú. Gracias por tu lección – bes67

+2

Nota: prefiera "acceso directo" a "control" (Windows) o "meta" (Mac) para mantener la plataforma independiente de la aplicación. – Puce

+2

Gracias Puce, es bueno usar 'SHORTCUT_DOWN' en lugar de' CONTROL_DOWN'. Actualicé la respuesta para incluir esta recomendación. – jewelsea