GraphStream 2.0 mouse pointer offset when dragging nodes (not solved)

233 Views Asked by At

I'm working with GraphStream and I can't get the mouse pointer to drag nodes correctly.

enter image description here

(Note how the mouse offset gets worse towards the bottom right corner).

This looks like exactly the same problem as here (similar to this, only for Swing instead of JavaFX).

I tried everything I could think of, read the GraphStream docs, FAQ, checked the tests, etc.

I also tried the suggested solution here, but it doesn't work - the behavior is exactly the same.

Here's my code (after applying the suggestion):

DefaultView view = (DefaultView) viewer.addView("Graph", new SwingGraphRenderer(), false);
view.setLayout(new BorderLayout());
view.setPreferredSize(frame.getSize());
view.setMouseManager(new DefaultMouseManager());
JPanel panel = new JPanel();
panel.add(view);
frame.add(panel);
view.setVisible(true);
panel.setVisible(true);

Here is the code for the full (minimalistic) example:

package main.java;

import org.graphstream.graph.Graph;
import org.graphstream.graph.Node;
import org.graphstream.graph.implementations.DefaultGraph;
import org.graphstream.ui.swing.SwingGraphRenderer;
import org.graphstream.ui.swing_viewer.DefaultView;
import org.graphstream.ui.swing_viewer.SwingViewer;
import org.graphstream.ui.swing_viewer.util.DefaultMouseManager;
import org.graphstream.ui.view.Viewer;

import javax.swing.*;
import java.awt.*;

public class Example {

    public static void main(String[] args) {

        System.setProperty("org.graphstream.ui", "swing");
        Graph g = new DefaultGraph("Graph");

        Node n1 = g.addNode("V1");
        Node n2 = g.addNode("V2");
        g.addEdge("E1", "V1", "V2");
        String style = "size: 30px; stroke-mode: plain; fill-color: rgba(223, 187, 254, 255);";
        n1.setAttribute("ui.style", style);
        n2.setAttribute("ui.style", style);

        // g.display(); <- same behavior as dropping everything below this line.

        JFrame frame = new JFrame();
        frame.setBounds(0, 0, 600, 600);
        frame.setLayout(new BorderLayout());

        SwingViewer viewer = new SwingViewer(g, Viewer.ThreadingModel.GRAPH_IN_ANOTHER_THREAD);
        viewer.enableAutoLayout();
        DefaultView view = (DefaultView) viewer.addView(g.getId(), new SwingGraphRenderer(), false);
        view.setLayout(new BorderLayout());
        view.setPreferredSize(frame.getSize());
        JPanel panel = new JPanel();
        panel.add(view);
        frame.add(panel);
        view.setMouseManager(new DefaultMouseManager());

        view.setVisible(true);
        panel.setVisible(true);
        frame.setVisible(true);
    }
}

And the pom.xml dependencies:

    <dependencies>
        <dependency>
            <groupId>org.graphstream</groupId>
            <artifactId>gs-core</artifactId>
            <version>2.0</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.graphstream/gs-ui-swing -->
        <dependency>
            <groupId>org.graphstream</groupId>
            <artifactId>gs-ui-swing</artifactId>
            <version>2.0</version>
        </dependency>
    </dependencies>
1

There are 1 best solutions below

2
On

Introduction

Let's consider the following versions as the current versions:

<dependencies>
    <dependency>
        <groupId>org.graphstream</groupId>
        <artifactId>gs-core</artifactId>
        <version>2.0</version>
    </dependency>
    <dependency>
        <groupId>org.graphstream</groupId>
        <artifactId>gs-ui-swing</artifactId>
        <version>2.0</version>
    </dependency>
</dependencies>

Intermediate root cause analysis

The GraphStream library does not handle UI scaling correctly.

It seems to be a known unresolved issue.

The related GitHub issues:

Precondition to reproduce issue

Force UI scaling by setting the sun.java2d.uiScale system property value to 200%.
For example, programmatically:

System.setProperty("sun.java2d.uiScale", "200%");

Possible solutions

Straightforward solution: Wait for next release with resolved issue

(Self-descriptive.)

Check and review fork of library: If acceptable, use it

Mentioned in the related GitHub issues.

GitHub issue comment:

LukasMolzberger commented on 2021-01-03T10:48:27Z

I think I've encountered the same problem here. It seems that the coordinates given by Point3 dst = bck.transform(elt.getX(), elt.getY(), 0); in the nodeContains(GraphicElement elt, double x, double y) method are twice as large as the coordinates given by the mouse pointer. g2.getTransform() seems to already contain this factor. I don't know to much about this stuff, but is there may be a difference between virtual and real pixels that needs to be converted somehow? (I'm using an UHD Display)

GitHub issue comment:

aika-algorithm commented on 2021-02-28T05:33:50Z

I've got it working on the branches https://github.com/aika-algorithm/gs-ui-swing and https://github.com/aika-algorithm/gs-core
The solution, however, is not very clean. The problem seems to be, that swing is using two different coordinate spaces on high-resolution displays.

-Lukas

Please, note the mentioned GitHub repositories:

Currently, the following latest versions of the Maven artifacts are available in the Maven central repository:

<dependencies>
    <dependency>
        <groupId>network.aika</groupId>
        <artifactId>gs-core</artifactId>
        <version>2.0.2</version>
    </dependency>
    <dependency>
        <groupId>network.aika</groupId>
        <artifactId>gs-ui-swing</artifactId>
        <version>2.0.2</version>
    </dependency>
</dependencies>

Create your own fork of library and resolve issue by yourself

(Self-descriptive.)

Workaround: If acceptable, disable UI scaling

Mentioned in the related GitHub issues.

GitHub issue comment:

ghost commented on 2018-11-21T19:18:03Z

I found the problem, Its a scaling issue on Java 9 and 10. You need the VM parameter
-Dsun.java2d.uiScale=100% /// For Swing
-Dglass.win.uiScale=100% /// for JavaFx

Also, add a Runtime check in the code
String scaleSwing=System.getProperty("sun.java2d.uiScale");
if(scaleSwing.equals("100%")==false) {throw new RuntimeException("invalid scaleSwing "+scaleSwing);}

then the DefaultCamera.Tx is correct . and you can select points on the graph.
The current Camera implementation doesn't work with the default JVM scaling for Java 9,10, which is usually 150% (on large displays)