How to catch and process JavaFX TouchEvent in Swin

2019-06-25 13:28发布

问题:

I developed a Swing application in which I now need to implement a customized multi-touch gesture.

After some research, the easiest approach seemes to be the use of JavaFX, because it can be embedded in Swing and provides events for every finger on the touch screen seperately. I then tried to implement touch handling according to the following examples:

http://docs.oracle.com/javafx/2/swing/swing-fx-interoperability.htm

http://docs.oracle.com/javafx/2/events/touch_events.htm

I decided to create a transparent JFXPanel above a JPanel catching all mouse and touch events. It works perfectly for JavaFX mouse events, but I don't recieve any touch events.

I tested my application on different touchable Windows 7 and Window 8 devices. I'm currently using Java JDK 1.8.0_45.

So my question is Why do I not recieve any touch events?

I reduced my problem to following two classes:

The GUI class:

import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;


public class TestWindow extends JFrame {

    private static final long serialVersionUID = 1L;
    private static final JFXPanel jfxPanel = new JFXPanel();
    private static Scene jfxScene;
    private static TestController controller;
    private boolean enableJFXPanel;

    /**
     * Create the Frame
     * @param tc The Application's controller
     */
    public TestWindow(TestController tc) {

        this.setBounds(200,200,400,400);
        this.setResizable(false);
        this.setTitle("JavaFX in Swing Test");
        getContentPane().setLayout(null);

        controller = tc;

        // Create the swing panel
        JPanel jPanel = new JPanel();
        jPanel.setBounds(0, 0, this.getWidth(), this.getHeight());
        jPanel.addMouseListener(controller);

        // Create the button
        JButton button = new JButton("show / hide JavaFX panel");
        button.setBounds((jPanel.getWidth()/2)-100, (jPanel.getHeight()/2)-25, 200, 50);
        button.addActionListener(controller);
        jPanel.add(button);

        // Create the JavaFX panel
        jfxPanel.setBounds(0, 0, 0, 0);
        enableJFXPanel = false;     
        jPanel.add(jfxPanel);

        getContentPane().add(jPanel);

        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                initAndShowGUI();
            }
        });

        this.setVisible(true);
    }

    /**
     * Initialize and Show JavaFX
     */
    private static void initAndShowGUI() {
        Platform.runLater(new Runnable() {
            @Override
            public void run() {
                initFX();
            }
        });
    }

    /**
     * Initialize the JavaFX {@code Scene} and set touch controller.
     */
    private static void initFX() {
        Group  jfx_root  =  new  Group();
        jfxScene  =  new  Scene(jfx_root);
        jfxScene.setFill(Color.AQUA);

        // Register touch event listener (DOESN'T WORK !!!)
        jfxScene.setOnTouchMoved(controller);
        jfxScene.setOnTouchPressed(controller);
        jfxScene.setOnTouchReleased(controller);
        jfxScene.setOnTouchStationary(controller);

        // Test catching JavaFX mouse events (WORKS PERFECTLY !!!)
        jfxScene.setOnMouseClicked(new EventHandler<MouseEvent>(){
            @Override
            public void handle(MouseEvent event) {
                System.out.println("MOUSE CLICKED ON JAVA FX PANEL");               
            }
        });

        jfxPanel.setScene(jfxScene);
    }

    /**
     * Show / hide the JavaFX panel
     */
    public void switchJFXPanel() {
        if (enableJFXPanel) {
            jfxPanel.setBounds(0, 0, 0, 0);
            enableJFXPanel = false;
        } else {
            jfxPanel.setBounds(0, 0, this.getWidth(), this.getHeight());
            enableJFXPanel = true;
        }
    }
}

The controller class:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javafx.scene.input.TouchEvent;

public class TestController implements MouseListener, ActionListener, javafx.event.EventHandler<TouchEvent> {

    private TestWindow testWindow;

    public TestController() {
        testWindow = new TestWindow(this);
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        System.out.println("MOUSE CLICKED ON JPANEL");
    }

    @Override
    public void mousePressed(MouseEvent e) {}
    @Override
    public void mouseReleased(MouseEvent e) {}
    @Override
    public void mouseEntered(MouseEvent e) {}
    @Override
    public void mouseExited(MouseEvent e) {}

    @Override
    public void actionPerformed(ActionEvent e) {
        testWindow.switchJFXPanel();
    }

    @Override
    public void handle(TouchEvent event) {
        // OCCURING JAVA FX TOUCH EVENT SHALL BE WRITTEN TO CONSOLE
        System.out.println("JAVA FX TOUCH EVENT: " + event.toString());     
    }

    public static void main(String arg[]) {
        TestController test = new TestController();
    }
}

Thanks for any help.