davidethell
davidethell

Reputation: 12018

Add touch gestures to legacy swing application

I have a legacy swing application that I need to add touch gestures to,specifically pinch to zoom and touch and drag.

I tried the SwingNode of JDK 8 and I can run the swing application there, but the display performance was cut by more than 50% which won't work. SwingTextureRenderer in MT4J has the same issue and that is without even trying to redispatch touch events as mouse events.

I thought about a glass pane approach using a JavaFX layer on top and capturing the touch events and attempting to dispatch them as mouse events to the Swing app underneath.

Does anyone have an alternative approach? The target platform is windows 8.

Bounty coming as soon as Stackoverflow opens it up. I need this one pretty rapidly.

EDIT:

Here is what I tried with SwingNode (the mouse redispatch didn't work). The SwingNode stuff might be a distraction from the best solution so ignore this if you have a better idea for getting touch into swing:

@Override
public void start(Stage stage) {
    final SwingNode swingNode = new SwingNode();
    createAndSetSwingContent(swingNode);

    StackPane pane = new StackPane();
    pane.getChildren().add(swingNode);

    stage.setScene(new Scene(pane, 640, 480));
    stage.show();
}

private void createAndSetSwingContent(final SwingNode swingNode) {
    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            UILib.setPlatformLookAndFeel();

            // create GraphViewTouch
            String datafile = null;
            String label = "label";

            final JPanel frame = GraphView.demoFrameless(datafile, label);
            swingNode.setContent(frame);
            swingNode.setOnZoom(new EventHandler<ZoomEvent>() {
                @Override public void handle(ZoomEvent event) {
                    MouseWheelEvent me = new MouseWheelEvent(frame, 1, System.currentTimeMillis(), 0, (int)Math.round(event.getSceneX()), (int)Math.round(event.getSceneY()), (int)Math.round(event.getScreenX()), (int)Math.round(event.getScreenY()), (int)Math.round(event.getZoomFactor()), false, MouseWheelEvent.WHEEL_UNIT_SCROLL, (int)Math.round(event.getZoomFactor()), (int)Math.round(event.getZoomFactor()), event.getZoomFactor());
                    frame.dispatchEvent(me);
                    System.out.println("GraphView: Zoom event" +
                        ", inertia: " + event.isInertia() + 
                        ", direct: " + event.isDirect());

                    event.consume();
                }
            });
        }
    });
}

Upvotes: 13

Views: 2856

Answers (3)

Charlie
Charlie

Reputation: 9118

You can use JNA to parse the messages from Windows.

Some documentation on the multi touch events from Microsoft: https://learn.microsoft.com/en-us/windows/desktop/wintouch/wm-touchdown

Some documentation on how to do it in Java and sample code: https://github.com/fmsbeekmans/jest/wiki/Native-Multitouch-for-AWT-component-(Windows)

Upvotes: 1

hnskns
hnskns

Reputation: 539

For the pinch-to-zoom:

Try the GestureMagnificationListener by guigarage.com. It provides a method:

public void magnify(GestureMagnificationEvent me){...}

Upvotes: 0

user3200756
user3200756

Reputation: 76

hmm... this is a tough one, but there is a chance.

What I would do is make multiple MouseListener classes (relative to the number of mouse events you want to pick up), and than create some sort of system to detect certain adjustments, eg. (zoom)

1st listener:

    public void mousePressed(MouseEvent e){
    //Set click to true
    clk = true;
    //set first mouse position
    firstPos = window.getMousePosition();
    }

    public void mouseReleased(MouseEvent e){

    //set second mouse position
    secondPos = window.getMousePosition();
    }

Second Listener

    public void mousePressed(MouseEvent e){
    //set clicked to true
    clk = true;
    //set first mouse position (listener 2)
    firstPos = window.getMousePosition();
    }

    public void mouseReleased(MouseEvent e){

    //set second mouse position
    secondPos = window.getMousePosition();
    }

Main handler

    if(Listener1.get1stMousePos() < Listener1.get2ndMousePos() &&    Listener2.get1stMousePos() < Listener2.get2ndMousePos() && Listener1.clk && Listener2.clk){
    zoomMethod((Listener1.get1stMousePos - Listener1.get2ndMousePos()) +           (Listener1.get1stListener2.get2ndMousePos());

    }

And than just do this to add it to the window:

    window.addMouseListener(Listener1);
    window.addMouseListener(Listener2);

Hope you find a way.

Upvotes: 0

Related Questions