2012-10-03 53 views
8

我正在嘗試使JavaFX助記符工作。我在場景中有一些按鈕,我想要實現的是按Ctrl + S來觸發此按鈕事件。 下面是一個代碼sceleton:使用JavaFX 2.2助記符(和加速器)

@FXML 
public Button btnFirst; 

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

巴頓的mnemonicParsing是假的。 (好吧,當試圖做這個工作時,我試圖將它設置爲true,但沒有結果)。 JavaFX文檔指出,當一個助記符在場景上註冊,並且KeyCombination未使用到場景時,目標節點將被髮送一個ActionEvent。但這不行,可能我做錯了...

我可以使用標準按鈕的助記符(通過將mnemonicParsing設置爲true並以'下劃線字符爲前綴'F'字母)。但是這種方式用戶必須使用Alt鍵,這會在帶有菜單欄的瀏覽器上帶來一些奇怪的行爲(如果應用程序被嵌入到網頁中,而不是通過按Alt + S觸發按鈕事件後激活瀏覽器的菜單)。 此外,標準的方式使得不可能做出像Ctrl + Shift + F3等快捷鍵。

那麼,如果有什麼辦法可以使這項工作?

回答

20

對於您的使用案例,我認爲您實際上想要使用加速器而不是助記符。

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

在大多數情況下,建議您使用KeyCombination.SHORTCUT_DOWN作爲修改符,如上面的代碼。這方面的一個很好的解釋是KeyCombination文檔中:

快捷修飾符用來表示修飾鍵是鍵盤快捷鍵常用的主機平臺上 。這是針對Windows上的 示例控件和Mac上的meta(命令鍵)。通過使用 快捷鍵修飾符,開發人員可以創建平臺無關的 快捷鍵。因此,「Shortcut + C」組合鍵在內部以 作爲Windows上的「Ctrl + C」和Mac上的「Meta + C」處理。

如果你想具體的代碼只能處理一按Ctrl + S組合鍵,就可以使用:

new KeyCodeCombination(KeyCode.S, KeyCombination.CONTROL_DOWN) 

以下是可執行例如:

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 

輸出示例:

Sample program output

+0

jewelsea,thank you ü。你絕對正確,加速器是我的用例。我錯誤地認爲加速器必須連接到菜單項。感謝您的教訓。 – bes67

+2

注意:比「控制」(Windows)或「元」(Mac)更喜歡「快捷方式」,以保持應用程序平臺無關。 – Puce

+2

感謝Puce,使用'SHORTCUT_DOWN'而不是'CONTROL_DOWN'是個不錯的選擇。我更新了包含此建議的答案。 – jewelsea