首页 > 解决方案 > 一旦按下指定的键,JavaFX 就会运行一个方法

问题描述

一旦使用 KeyListener 按下指定的键,我试图在为特定任务指定的控制器类中运行一个方法。但我无法检测到按键并调用该java.awt.event keyPressed方法。我的代码如下:

public class POSController implements KeyListener {

@Override
public void keyPressed(java.awt.event.KeyEvent e) {
    if (e.getKeyCode() == com.sun.glass.events.KeyEvent.VK_F1) {
        try {
            paymentAction();
         } catch (Exception e1) {
            e1.printStackTrace();
       }
     }
  }
}

可能出了什么问题?提前致谢。

这是该问题的最小可执行示例。

public class POSController implements KeyListener {

@FXML
private TableView<Product> productTableView;
@FXML
private TableView<Item> listTableView;
@FXML
private MenuItem logoutItem, profile;
@FXML
private javafx.scene.image.ImageView backImage;
@FXML
private MenuButton menuButton;
@FXML
private TableColumn<Item, String> itemColumn;
@FXML
private ComboBox<String> clientId, paymentMethod;
@FXML
private TableColumn<Item, Double> priceColumn, totalColumn, discountPercentageColumn, amountColumn;
@FXML
private TableColumn<Item, Integer> quantityColumn;
@FXML
private TableColumn<Product, String> productColumn;
@FXML
private TextField searchField,discountPercentage,productField,priceField,quantityField,vatPercentage,subTotalField,discountField,totalVatField,vatField,netPayableField,totalDiscountField;
@FXML
private TextField ;
@FXML
private TextField ;
@FXML
private TextField ;
@FXML
private TextField ;
@FXML
private TextArea descriptionArea;
@FXML
private Button addButton, removeButton, paymentButton, resetTableButton, resetButton;
@FXML
private Label quantityLabel, errorLabel, userName, backLabel;
@FXML
private ObservableList<Item> ITEMLIST;

public static Scene paymentScene;
private double xOffset = 0;
private double yOffset = 0;
public static double finalNetPayablePrice = 0.0;
public static double finalSubTotalPrice = 0.0;
public static double finalVat = 0.0;
public static double finalDiscount = 0.0;
public static String clientName = null;
public static String selectedPaymentMethod = null;
public static List<String> itemNames = new ArrayList<>();
public static List<Double> itemDiscounts = new ArrayList<>();
public static List<String> prices = new ArrayList<>();
public static List<String> quantities = new ArrayList<>();
public static List<String> subTotals = new ArrayList<>();
public static ObservableList<Item> itemList;
public static List<String> columnItemData = new ArrayList<>();
public static List<String> columnQuantityData = new ArrayList<>();

@FXML
private void initialize() throws SQLException, ClassNotFoundException, IOException {

ObservableList<Product> productsData = ProductDAO.searchGoodProducts(app.values.getProperty("STATUS_TYPE1"));
populateProducts(productsData);

 }

@FXML
private void populateProducts(ObservableList<Product> productData) throws ClassNotFoundException {
    productTableView.setItems(productData);
}

@Override
public void keyTyped(java.awt.event.KeyEvent e) {

}

@Override
public void keyPressed(java.awt.event.KeyEvent e) {

    if (e.getKeyCode() == java.awt.event.KeyEvent.VK_F1) {

        try {
            paymentAction();
        } catch (Exception e1) {
            e1.printStackTrace();
        }
    }

}

@Override
public void keyReleased(java.awt.event.KeyEvent e) {

}

@FXML
public void paymentAction() throws Exception {

    if (validateInputsForPayment()) {
        Payment payment = new Payment();
        FXMLLoader loader = new FXMLLoader((getClass().getResource(app.values.getProperty("INVOICE_VIEW_LOCATION"))));
        Parent root = loader.load();
        Stage stage = new Stage();
        root.setOnMousePressed((MouseEvent e) -> {
            xOffset = e.getSceneX();
            yOffset = e.getSceneY();
        });
        root.setOnMouseDragged((MouseEvent e) -> {
            stage.setX(e.getScreenX() - xOffset);
            stage.setY(e.getScreenY() - yOffset);
        });
        Scene scene = new Scene(root);
        stage.initModality(Modality.APPLICATION_MODAL);
        stage.initStyle(StageStyle.UNDECORATED);
        stage.setScene(scene);
        this.paymentScene = scene;
        stage.showAndWait();
    }
}

标签: javafxkeypress

解决方案


您不应该使用java.awt.event.KeyListenerJavaFX 应用程序。JavaFX 有自己的一套事件 API。

假设这POSController是特定 FXML 的控制器类:

public class POSController {
    @FXML private BorderPane root; // Or any other Node from FXML file

    @FXML private void initialize() {
        javafx.event.EventHandler<javafx.scene.input.KeyEvent> handler = event -> {
            if (event.getCode() == javafx.scene.input.KeyCode.F1) {
                try {
                    paymentAction();
                } catch (Exception e1) {
                    e1.printStackTrace();
                }
            }
        };

        // I'm using root to get scene, but any node would be fine
        if (root.getScene() != null) {
            root.getScene().addEventHandler(javafx.scene.input.KeyEvent.KEY_PRESSED, handler);
        }
        else {
            root.sceneProperty().addListener((obs, oldScene, newScene) -> {
                if (newScene != null) {
                    root.getScene().addEventHandler(javafx.scene.input.KeyEvent.KEY_PRESSED, handler);
                }
            });
        }
    }
}

这会将关键事件添加到Scene. 如果您不需要在场景范围内应用此事件,则可以在其他适当的节点添加事件处理程序。

更新

如果场景中有任何输入控件,那么您可能需要使用setEventFilter()而不是setEventHandler(). 这是因为这些控件可能会在事件冒泡阶段消耗关键事件。


推荐阅读