首页 > 解决方案 > Java JFXPanel:eventHandler返回按钮被按住而不是按钮被按下

问题描述

我正在尝试为单击设置一个事件处理程序,以添加到 JFXPanel 内的场景中:

scene.addEventHandler(MouseEvent.MOUSE_PRESSED, event -> System.out.println("Button pressed: " + event.getButton().name()));

奇怪的是,如果我按住主按钮并单击辅助按钮或中间按钮,则返回的按钮event.getButton()是主按钮,而不是触发单击的按钮。

例如,如果我按住主按钮并单击中间按钮,上面的代码将有控制台打印Button pressed: PRIMARY

我在一个纯粹的 JavaFX 应用程序中尝试过,getButton()总是返回按下的按钮;因此问题出在 JFXPanel 上。

这种奇怪的行为是否有解释或解决方法?

这是一个完整的例子:

import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

public class Test {
    public static void main(String[] args) { SwingUtilities.invokeLater(Test::initAndShowGUI); }

    private static void initAndShowGUI() {
        // Setup the JFXPanel inside a JPanel
        JFrame frame = new JFrame();
        final JFXPanel fxPanel = new JFXPanel();
        frame.add(fxPanel);
        frame.setSize(300, 200);
        frame.setVisible(true);

        Platform.runLater(() -> initFX(fxPanel));
    }

    private static void initFX(JFXPanel fxPanel) {
        Group  root = new Group();
        Scene scene = new Scene(root);

        // The event handler that incorrectly returns the button held instead of the one pressed
        scene.addEventHandler(MouseEvent.MOUSE_PRESSED, event -> System.out.println("Button pressed: " + event.getButton().name()));

        fxPanel.setScene(scene);
    }
}

运行上面的代码并在按住主要按钮的同时单击辅助按钮以获取消息“按下按钮:PRIMARY”而不是“按下按钮:SECONDARY”。

我对其进行了测试,Java 10 和 Java 14 中都存在这种行为。它也存在于MOUSE_RELEASEDMOUSE_CLICKED.

标签: javajavafxmouseeventjfoenix

解决方案


这是Java中的当前错误。

错误的来源是packagemouseButtonToEmbedMouseButton类中的函数。SwingEventscom.sun.javafx.embed.swing

该函数应该将 Swing 鼠标按钮转换为 JavaFX 鼠标按钮。

作为说明,以下代码

SwingEvents.mouseButtonToEmbedMouseButton(intButton, MouseEvent.BUTTON1_DOWN_MASK)

将永远返回1,无论intButton取什么值。

查看源代码mouseButtonToEmbedMouseButton,问题在于 if 语句

if ((extModifiers & MouseEvent.BUTTON1_DOWN_MASK) != 0){
    abstractButton = AbstractEvents.MOUSEEVENT_PRIMARY_BUTTON;}

其中extModifiers是函数的第二个参数。因此,如果extModifiersMouseEvent.BUTTON1_DOWN_MASKabstractButton(返回的内容)将始终设置为 1。


推荐阅读