我的用户界面有一个添加按钮,我想为其分配键盘快捷键组合。我没有为此目的使用setAcceleartor。 在javafx应用程序中设置键盘快捷键的最简单方法是什么?
UI中的按钮声明:
<Button fx:id="addButton" alignment="CENTER" minWidth="-Infinity" mnemonicParsing="false" onAction="#addAction" prefHeight="31.0" prefWidth="130.0" text="Add" HBox.hgrow="ALWAYS" />
控制器按钮绑定:
@FXML
private Button addButton;
想要为按钮的快捷方式设置setOnAction的方法:
public void addAction(ActionEvent event) throws SQLException, ClassNotFoundException {
if (validateInput()) {
String productName = productField.getText();
double unitPrice = Double.parseDouble(priceField.getText());
int quantity = Integer.parseInt(quantityField.getText());
double total = unitPrice * quantity;
ITEMLIST.add(new Item(productName, unitPrice, quantity, total));
calculation();
resetAdd();
productTableView.getSelectionModel().clearSelection();
ObservableList<Product> productsData = ProductDAO.searchProducts();
populateProducts(productsData);
searchField.setText("");
}
}
initialize()方法:
@FXML
private void initialize() throws SQLException, ClassNotFoundException, IOException {
setSaveAccelerator(addButton);
}
我尝试使用setAccelerator的代码:
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() {
@FXML public void run() {
button.fire();
}
}
);
}
答案 0 :(得分:1)
在setSaveAccelerator
方法中,只需指示按钮将其事件触发到其侦听器,例如:addAction(ActionEvent event)
,而不是直接调用button.fire()
。例如:
private void setSaveAccelerator(Button button) {
if(button==null) {
System.out.println("Button is null! "); // check that the button was injected properly through your fxml
}
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() {
@FXML public void run() {
button.fire();
}
}
);
}
修改强>
要避免IllegalArgumentException
,必须在按钮附加到场景后附加加速器。我设法通过在控制器中创建一个公共方法来实现这一点,以便在设置场景后附加加速器。然后,在加载场景的类中,可以调用控制器的方法来设置该功能。请参阅以下示例:
在控制器类中(在我的情况下为MainController
):
public void setup() {
setSaveAccelerator(button);
}
加载fxml文件时在主类中:
FXMLLoader loader = new FXMLLoader(MainController.class.getResource("mainFXML.fxml"));
AnchorPane page = (AnchorPane) loader.load();
MainController controller = loader.getController();
Scene scene = new Scene(page);
controller.setup(); // calls the setup method attaching the accelerators
完整示例
主要课程:
public class Main extends Application{
public static Stage primaryStage;
@Override
public void start(Stage primaryStage) throws Exception {
Main.primaryStage=primaryStage;
FXMLLoader loader = new FXMLLoader(MainController.class.getResource("mainFXML.fxml"));
AnchorPane page = (AnchorPane) loader.load();
MainController controller = loader.getController();
Scene scene = new Scene(page);
primaryStage.setTitle("Shortcut example");
primaryStage.setScene(scene);
controller.setup();
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Maincontroller:
public class MainController {
@FXML
private ResourceBundle resources;
@FXML
private URL location;
@FXML
private Button button;
@FXML
private AnchorPane rootPane;
@FXML
private TextArea textarea;
@FXML
void action(ActionEvent event) {
textarea.setText("Action fired!!");
}
@FXML
void initialize() {
assert button != null : "fx:id=\"button\" was not injected: check your FXML file 'MainFXML.fxml'.";
assert rootPane != null : "fx:id=\"rootPane\" was not injected: check your FXML file 'MainFXML.fxml'.";
assert textarea != null : "fx:id=\"textarea\" was not injected: check your FXML file 'MainFXML.fxml'.";
}
public void setup() {
setSaveAccelerator(button);
}
private void setSaveAccelerator(Button button) {
if(button==null) {
System.out.println("Button null!!");
}
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() {
@FXML public void run() {
button.fire();
}
}
);
}
}
MainFXML.fxml
<AnchorPane fx:id="rootPane" prefHeight="408.0" prefWidth="330.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.MainController">
<children>
<Button fx:id="button" layoutX="139.0" layoutY="350.0" mnemonicParsing="false" onAction="#action" text="Button" />
<TextArea fx:id="textarea" layoutX="73.0" layoutY="38.0" prefHeight="200.0" prefWidth="200.0" />
</children>
</AnchorPane>