How to programatically pan a VisualizationViewer with Jung (the java library)?

不想你离开。 提交于 2019-12-05 10:10:35

问题


After a lot a investigations, I don't achieve to find a convenient answer to the following question: how to programatically pan a VisualizationViewer with Jung?

I have a GUI with the list of the vertices of my graph, and I want that a double click on one item of the list (i.e. a node description) perform a "centering action" of my VisualizationViewer for the clicked node. How to code such a behavior? it seems simple but I found no convenient answer.

If someone could help, thanks!

njames


回答1:


Here is how to popup a menu after right-clicking on a node in JUNG2 and later choose to center to this node:

graphMouse.add(new MyPopupGraphMousePlugin());

/**
 * a GraphMousePlugin that offers popup
 * menu support
 */
protected class MyPopupGraphMousePlugin extends AbstractPopupGraphMousePlugin
implements MouseListener {

    public MyPopupGraphMousePlugin() {
        this(MouseEvent.BUTTON3_MASK);
    }
    public MyPopupGraphMousePlugin(int modifiers) {
        super(modifiers);
    }

    /**
     * If this event is over a node, pop up a menu to
     * allow the user to center view to the node
     *
     * @param e
     */
    protected void handlePopup(MouseEvent e) {
        final VisualizationViewer<Node,Link> vv =
            (VisualizationViewer<Node,Link>)e.getSource();
        final Point2D p = e.getPoint(); 

        GraphElementAccessor<Node,Link> pickSupport = vv.getPickSupport();
        if(pickSupport != null) {
            final Node station = pickSupport.getVertex(vv.getGraphLayout(), p.getX(), p.getY());
            if(station != null) {
                JPopupMenu popup = new JPopupMenu();

                String center = "Center to Node";

                popup.add(new AbstractAction("<html><center>" + center) {
                    public void actionPerformed(ActionEvent e) {

                        MutableTransformer view = vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW);
                        MutableTransformer layout = vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT);

                        Point2D ctr = vv.getCenter(); 
                        Point2D pnt = view.inverseTransform(ctr);

                        double scale = vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW).getScale();

                        double deltaX = (ctr.getX() - p.getX())*1/scale;
                        double deltaY = (ctr.getY() - p.getY())*1/scale;
                        Point2D delta = new Point2D.Double(deltaX, deltaY);

                        layout.translate(deltaX, deltaY);
                    }
                });

                popup.show(vv, e.getX(), e.getY());
            } else {

            }
        }
    }
}

Edited: Finally! the correct node-to-center-view with scale factor calculation...




回答2:


public void centerViewsOnVertex(SynsetVertex v) {
  //the following location have sense in the space of the layout
  Point2D v_location = layout.transform(v);
  Point2D vv1_center_location = vv1.getRenderContext()
                .getMultiLayerTransformer()
                .inverseTransform(Layer.LAYOUT, vv1.getCenter());

  double scale = vv1.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW).getScale();

  vv1.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT).translate(
                        -(v_location.getX() - vv1_center_location.getX()) * 1
                                / scale,
                        -(v_location.getY() - vv1_center_location.getY()) * 1
                                / scale);

  refreshViews();
}



回答3:


Since I was just looking for an answer to this and the above worked terribly; here's a code snippet I found in AnimatedPickingGraphMousePlugin that will recenter:

Layout<V,E> layout = vv.getGraphLayout();
Point2D q = layout.transform(vertex);
Point2D lvc = 
    vv.getRenderContext().getMultiLayerTransformer().inverseTransform(vv.getCenter());
final double dx = (lvc.getX() - q.getX());
final double dy = (lvc.getY() - q.getY());
vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT).translate(dx, dy);



回答4:


Actually, I have found by the next a solution:

//the following location have sense in the space of the layout
    Point2D v_location = layout.transform(v);
    Point2D vv1_center_location = vv1.getRenderContext()
            .getMultiLayerTransformer()
            .inverseTransform(Layer.LAYOUT, vv1.getCenter());

    vv1.getRenderContext()
            .getMultiLayerTransformer()
            .getTransformer(Layer.LAYOUT)
            .translate(-(v_location.getX() - vv1_center_location.getX()),
                    -(v_location.getY() - vv1_center_location.getY()));



回答5:


The center on node function is already implemented in the AnimatedPickingGraphMousePlugin

http://sourceforge.net/p/jung/discussion/252062/thread/18b4b941

In picking mode ctrl+click on a vertex to center on it.

@SuppressWarnings("unchecked")
public void mouseReleased(MouseEvent e) {
    if (e.getModifiers() == modifiers) {
        final VisualizationViewer<V,E> vv = (VisualizationViewer<V,E>) e.getSource();
        if (vertex != null) {
            Layout<V,E> layout = vv.getGraphLayout();
            Point2D q = layout.transform(vertex);
            Point2D lvc = vv.getRenderContext().getMultiLayerTransformer().inverseTransform(vv.getCenter());
            final double dx = (lvc.getX() - q.getX()) / 10;
            final double dy = (lvc.getY() - q.getY()) / 10;

            Runnable animator = new Runnable() {

                public void run() {
                    for (int i = 0; i < 10; i++) {
                        vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT).translate(dx, dy);
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException ex) {
                        }
                    }
                }
            };
            Thread thread = new Thread(animator);
            thread.start();
        }
    }
}



回答6:


I was trying to figure out how to center on a given vertex and came across this, but unfortunately it was not particularly helpful and I spent a fair amount of time figuring out how to do it. So, sharing my experience here in case it may be helpful for others.

The application I'm writing has a VisualizationViewer, that is loaded inside a GraphZoomScrollPane. I have a GraphMouseListener that I've added to the VisualizationViewer, which allows a user to right click on a vertex in the viewable area of the scroll pane and in the popup menu they can choose to center on the vertex.

The top voted answer on this thread references usage of a MutableTransformer from the LAYOUT layer and it uses the translate method of that transformer to do the centering action. Unfortunately, if you are using a zoom/scroll then you don't really know the size and positioning of the layout layer in relation to the view layer without doing a bunch of extra math.

When using zoom/scroll pane, I'd recommend finding the location of the vertex in the viewable area of the graph as represented by the pane, and then adjusting where the view pane is at.

Here is a snippet of the code I worked out:

void center(MouseEvent me, GraphZoomScrollPane gzsp) {
  VisualizationViewer<V,E> vv = 
    (VisualizationViewer<V,E>)me.getSource();
  MutableTransformer viewTransformer = 
    vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW);
  double scaleFromViewTransformer = viewTransformer.getScale();
  Dimension paneSize = gzsp.getSize();
  Point2D positionOfVertexInPane = me.getPoint();
  double[] centerOfPane = new double[] {
    paneSize.getWidth()/2d, 
    paneSize.getHeight()/2d
  };
  double[] amountToMovePane = new double[] {
    (centerOfPane[0]-positionOfVertexInPane.getX())/scaleFromViewTransformer,
    (centerOfPane[1]-positionOfVertexInPane.getY())/scaleFromViewTransformer
  };
  viewTransformer.translate(amountToMovePane[0], amountToMovePane[1]);
}


来源:https://stackoverflow.com/questions/5745183/how-to-programatically-pan-a-visualizationviewer-with-jung-the-java-library

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!