如何使用Jung(java库)以编程方式平移VisualizationViewer?

时间:2011-04-21 14:04:08

标签: java graph visualization jung

经过大量的调查后,我无法找到以下问题的方便答案:如何用Jung以编程方式平移VisualizationViewer?

我有一个GUI,其中包含我的图形顶点列表,我希望双击列表中的一个项目(即节点描述),对我单击的节点执行VisualizationViewer的“居中操作”。 如何编码这样的行为?看起来很简单,但我找不到方便的答案。

如果有人可以提供帮助,谢谢!

njames

6 个答案:

答案 0 :(得分:4)

以下是在右键单击JUNG2中的节点后弹出菜单,然后选择居中到此节点:

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 {

            }
        }
    }
}

编辑:最后!具有比例因子计算的正确的节点到中心视图......

答案 1 :(得分:1)

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();
}

答案 2 :(得分:1)

因为我只是在寻找答案,而上述工作非常糟糕;这是我在AnimatedPickingGraphMousePlugin中找到的代码片段,它将重新定位:

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);

答案 3 :(得分:0)

实际上,我已经找到了下一个解决方案:

//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()));

答案 4 :(得分:0)

节点功能的中心已经在AnimatedPickingGraphMousePlugin

中实现

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

在拣选模式中,按住Ctrl键并点击顶点以使其居中。

@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();
        }
    }
}

答案 5 :(得分:0)

我试图找出如何以给定顶点为中心并遇到这个问题,但不幸的是它并没有特别有用,我花了相当多的时间来弄清楚如何去做。所以,在这里分享我的经验,以防它可能对其他人有所帮助。

我写的应用程序有一个VisualizationViewer,它被加载到GraphZoomScrollPane中。我有一个GraphMouseListener,我已经添加到VisualizationViewer,它允许用户右键单击滚动窗格的可视区域中的顶点,并在弹出菜单中,他们可以选择以顶点为中心。

此线程的最高投票回答引用了LAYOUT层中MutableTransformer的用法,并使用该转换器的translate方法进行居中操作。不幸的是,如果你使用缩放/滚动,那么你就不会真正了解布局图层相对于视图图层的大小和位置,而无需进行大量的额外数学运算。

使用缩放/滚动窗格时,我建议在窗格所代表的图形的可视区域中找到顶点的位置,然后调整视图窗格所在的位置。

以下是我编写的代码片段:

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]);
}