Button 使用JavaFX2.2助记符(和加速器)

Button 使用JavaFX2.2助记符(和加速器),button,javafx-2,javafx,shortcut,Button,Javafx 2,Javafx,Shortcut,我正在努力使JavaFX助记功能发挥作用。我在场景中有一些按钮,我想要实现的是通过按下Ctrl+S来触发这个按钮事件。 下面是一个代码sceleton: @FXML public Button btnFirst; btnFirst.getScene().addMnemonic(new Mnemonic(btnFirst, new KeyCodeCombination(KeyCode.S, KeyCombination.CONTROL_DOWN))); 按钮的助记符设

我正在努力使JavaFX助记功能发挥作用。我在场景中有一些按钮,我想要实现的是通过按下Ctrl+S来触发这个按钮事件。 下面是一个代码sceleton:

@FXML
public Button btnFirst;

btnFirst.getScene().addMnemonic(new Mnemonic(btnFirst, 
            new KeyCodeCombination(KeyCode.S, KeyCombination.CONTROL_DOWN)));
按钮的助记符设置为false。(好吧,虽然我试图使这项工作,我试图把它设置为真的,但没有结果)。JavaFX文档指出,当在场景中注册了助记符,并且KeyCombination未使用就到达场景时,目标节点将被发送一个ActionEvent。但这不起作用,可能我做错了

我可以使用标准按钮的助记符(通过将助记符Passing设置为true,并通过下划线字符前缀“F”字母)。但这种方式用户必须使用Alt键,这会在带有菜单栏的浏览器上带来一些奇怪的行为(如果应用程序嵌入到网页中,则在按下Alt+s触发按钮事件后,浏览器的菜单会被激活)。 除此之外,标准的方式使它不可能像Ctrl+Shift+F3这样的快捷键


所以,如果有什么方法可以让它工作的话?

对于您的用例,我认为您实际上想要使用加速器而不是助记符

button.getScene().getAccelerators().put(
  new KeyCodeCombination(KeyCode.S, KeyCombination.SHORTCUT_DOWN), 
  new Runnable() {
    @Override public void run() {
      button.fire();
    }
  }
);
在大多数情况下,建议您使用KeyCombination.SHORTCUT\u DOWN作为修饰符说明符,如上面的代码所示。文档中对此有很好的解释:

快捷方式修改器用于表示修改器键,该键为 常用于主机平台上的键盘快捷键。这是给你的 Windows上的示例控件和Mac上的meta(命令键)。利用 快捷键修改器开发人员可以创建独立于平台的 捷径。因此,“快捷方式+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
导入javafx.animation.*;
导入javafx.application.application;
导入javafx.event.*;
导入javafx.geometry.Pos;
导入javafx.scene.scene;
导入javafx.scene.control.*;
导入javafx.scene.image.*;
导入javafx.scene.input.*;
导入javafx.scene.layout.VBox;
导入javafx.stage.stage;
导入javafx.util.Duration;
公共类SaveMe扩展了应用程序{
@覆盖公共无效开始(最终阶段)引发异常{
最终标签响应=新标签();
最终图像视图=新图像视图(
新图像(“http://icons.iconarchive.com/icons/gianni-polito/colobrush/128/software-emule-icon.png")
);
最终按钮=新按钮(“保存我”,图像视图);
button.setStyle(“-fx base:burlywood;”);
按钮.setContentDisplay(ContentDisplay.TOP);
displayFlashMessageOnAction(按钮,响应,“您已保存!”);
布局场景(按钮、响应、舞台);
stage.show();
设置加速键(按钮);
}
//将按钮的保存快捷键设置为Ctrl+S组合键。
专用void setSaveAccelerator(最终按钮){
Scene-Scene=button.getScene();
如果(场景==null){
抛出新的IllegalArgumentException(“当按钮连接到场景时必须调用setSaveAccelerator”);
}
scene.getAccelerators().put(
新的KeyCodeCombination(KeyCode.S、KeyCombination.SHORTCUT\u DOWN),
新的Runnable(){
@重写公共无效运行(){
消防按钮(按钮);
}
}
);
}
//从代码触发按钮,提供按钮正在触发的视觉反馈。
专用无效fireButton(最终按钮){
按钮。手臂();
PauseTransition pt=新的PauseTransition(持续时间.毫秒(300));
pt.setOnFinished(新事件处理程序
  • 以及相关的
  • 链接的问题报告包括一个变通方法,可用于在应用程序的多个位置(例如,在不同上下文菜单中的两个不同菜单项上)定义和使用同一加速器


    请注意,这仅适用于在应用程序中的多个位置尝试使用同一加速器,如果您不需要尝试,则可以忽略此信息。

    jewelsea,谢谢。您完全正确,加速器是我的用例。我错误地认为加速器必须连接到菜单项。谢谢您的支持我们的教训。注意:为了保持应用程序平台的独立性,您更喜欢“快捷方式”而不是“控制”(Windows)或“元”(Mac)。感谢Puce,使用
    快捷方式
    ,而不是
    控制
    。我更新了答案以包含此建议。URL已更改,但我在此处找到它:“感谢dmolony,我编辑了答案以包含更新的图标链接。