如何使用Gephi Toolkit开发交互式图形?

时间:2013-03-16 08:57:44

标签: graph preview interactive gephi

我正在尝试使用Gephi Toolkit创建图表Applet并将其集成到我们的JavaEE网站中。但问题是Gephi Toolkit(预览API)几乎没有支持交互功能。

根据Gephi论坛上的this topic,应该实现鼠标监听器来处理鼠标事件,例如点击节点。但是,我没弄清楚......有人可以帮我吗?

代码: 我创建了一个显示随机图形的类(没有问题),然后我添加了一个实现 PreviewMouseListener 的新类,只需在点击一个节点时打印一个msg。

    /*
    Copyright 2008-2010 Gephi
    Authors : Mathieu Bastian <mathieu.bastian@gephi.org>
    Website : http://www.gephi.org

    This file is part of Gephi.

    Gephi is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as
    published by the Free Software Foundation, either version 3 of the
    License, or (at your option) any later version.

    Gephi is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with Gephi.  If not, see <http://www.gnu.org/licenses/>.
     */

    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.event.MouseEvent;
    import java.awt.event.MouseListener;
    import java.io.File;

    import javax.swing.JFrame;

    import org.gephi.graph.api.GraphController;
    import org.gephi.graph.api.GraphModel;
    import org.gephi.graph.api.NodeIterator;
    import org.gephi.io.generator.plugin.RandomGraph;
    import org.gephi.io.importer.api.Container;
    import org.gephi.io.importer.api.ContainerFactory;
    import org.gephi.io.importer.api.ImportController;
    import org.gephi.io.processor.plugin.DefaultProcessor;
    import org.gephi.layout.plugin.random.Random;
    import org.gephi.layout.plugin.random.RandomLayout;
    import org.gephi.preview.api.PreviewController;
    import org.gephi.preview.api.PreviewModel;
    import org.gephi.preview.api.PreviewProperty;
    import org.gephi.preview.api.ProcessingTarget;
    import org.gephi.preview.api.RenderTarget;
    import org.gephi.preview.types.DependantOriginalColor;
    import org.gephi.project.api.ProjectController;
    import org.gephi.project.api.Workspace;
    import org.openide.util.Lookup;

    import processing.core.PApplet;

    /**
     *
     * @author Mathieu Bastian
     */
    public class PreviewJFrame {

        public void script() {
            //Init a project - and therefore a workspace
            ProjectController pc = Lookup.getDefault().lookup(ProjectController.class);
            pc.newProject();
            Workspace workspace = pc.getCurrentWorkspace();

            //Generate a random graph
            Container container = Lookup.getDefault().lookup(ContainerFactory.class).newContainer();
            RandomGraph randomGraph = new RandomGraph();
            randomGraph.setNumberOfNodes(50);
            randomGraph.setWiringProbability(0.005);
            randomGraph.generate(container.getLoader());

            //Append imported data to GraphAPI
            ImportController importController = Lookup.getDefault().lookup(ImportController.class);
            importController.process(container, new DefaultProcessor(), workspace);
            GraphModel graphModel = Lookup.getDefault().lookup(GraphController.class).getModel();

            //Preview configuration
            PreviewController previewController = Lookup.getDefault().lookup(PreviewController.class);
            PreviewModel previewModel = previewController.getModel();
            previewModel.getProperties().putValue(PreviewProperty.SHOW_NODE_LABELS, Boolean.TRUE);
            previewModel.getProperties().putValue(PreviewProperty.NODE_LABEL_COLOR, new DependantOriginalColor(Color.WHITE));
            previewModel.getProperties().putValue(PreviewProperty.EDGE_CURVED, Boolean.TRUE);
            previewModel.getProperties().putValue(PreviewProperty.EDGE_OPACITY, 50);
            previewModel.getProperties().putValue(PreviewProperty.EDGE_RADIUS, 10f);
            previewModel.getProperties().putValue(PreviewProperty.BACKGROUND_COLOR, Color.BLACK);
            previewController.refreshPreview();

            //New Processing target, get the PApplet
            ProcessingTarget target = (ProcessingTarget) previewController.
                    getRenderTarget(RenderTarget.PROCESSING_TARGET);
            PApplet applet = target.getApplet();
            applet.init();

            //Refresh the preview and reset the zoom
            previewController.render(target);
              RandomLayout layout = new RandomLayout(new Random(),1500);
              layout.setGraphModel(graphModel);
              layout.initAlgo();
              layout.goAlgo();
              layout.endAlgo();
              //Add the applet to a JFrame and display--------------------------------------
              JFrame frame = new JFrame("Test Preview");
              frame.setLayout(new BorderLayout());

              frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
              frame.add(applet, BorderLayout.CENTER);

              frame.pack();
              frame.setVisible(true);
              target.refresh();
              target.resetZoom();
        }

        public static void main(String[] args) {
            PreviewJFrame previewJFrame = new PreviewJFrame();
            previewJFrame.script();
        }
    }

的MouseListener:

    import org.gephi.preview.api.PreviewMouseEvent;
    import org.gephi.preview.api.PreviewProperties;
    import org.gephi.preview.spi.MouseResponsiveRenderer;
    import org.gephi.preview.spi.PreviewMouseListener;
    import org.gephi.project.api.Workspace;
    import org.openide.util.lookup.ServiceProvider;

    @ServiceProvider(service = PreviewMouseListener.class)
    public class AtosPreviewMouseListener implements PreviewMouseListener{
        @Override
        public void mouseClicked(PreviewMouseEvent event,
                PreviewProperties properties, Workspace workspace) {
            System.out.println("I'm clicked!!");
        }
        @Override
        public void mousePressed(PreviewMouseEvent event,
                PreviewProperties properties, Workspace workspace) {}
        @Override
        public void mouseDragged(PreviewMouseEvent event,
                PreviewProperties properties, Workspace workspace) {}
        @Override
        public void mouseReleased(PreviewMouseEvent event,
                PreviewProperties properties, Workspace workspace) {}
    }

非常感谢!

PS:我已经尝试回复该主题,但我的帐户尚未激活,即使我认为我在很多天前注册了...

2 个答案:

答案 0 :(得分:1)

我和gephi玩了几天,我很确定没有办法点击确切的节点。它的API似乎并没有考虑到交互性。但是我发现这对2D图形来说效果相当不错。

主类:

import java.awt.BorderLayout;
import java.awt.Color;
import javax.swing.JFrame;
import org.gephi.graph.api.*;
import org.gephi.io.processor.plugin.DefaultProcessor;
import org.gephi.preview.api.PreviewController;
import org.gephi.preview.api.PreviewModel;
import org.gephi.preview.api.PreviewProperty;
import org.gephi.preview.api.ProcessingTarget;
import org.gephi.preview.api.RenderTarget;
import org.gephi.preview.types.DependantOriginalColor;
import org.gephi.project.api.ProjectController;
import org.gephi.project.api.Workspace;
import org.openide.util.Lookup;
import processing.core.PApplet;

/**
 * This demo shows basic features from GraphAPI, how to create and query a graph
 * programmatically.
 * 
 * @author Mathieu Bastian
 */
public class TestGraph {


public void script() {
    //Init a project - and therefore a workspace
    ProjectController pc = Lookup.getDefault().lookup(ProjectController.class);
    pc.newProject();
    Workspace workspace = pc.getCurrentWorkspace();

    //Get a graph model - it exists because we have a workspace
    GraphModel graphModel = Lookup.getDefault().lookup(GraphController.class).getModel();

    //Create three nodes
    Node n0 = graphModel.factory().newNode("n0");
    n0.getNodeData().setLabel("Node 0");
    Node n1 = graphModel.factory().newNode("n1");
    n1.getNodeData().setLabel("Node 1");
    Node n2 = graphModel.factory().newNode("n2");
    n2.getNodeData().setLabel("Node 2");

    //Create three edges
    Edge e1 = graphModel.factory().newEdge(n1, n2, 1f, true);
    Edge e2 = graphModel.factory().newEdge(n0, n2, 2f, true);
    Edge e3 = graphModel.factory().newEdge(n2, n0, 2f, true);   //This is e2's mutual edge

    //Append as a Directed Graph
    DirectedGraph directedGraph = graphModel.getDirectedGraph();
    directedGraph.addNode(n0);
    directedGraph.addNode(n1);
    directedGraph.addNode(n2);
    directedGraph.addEdge(e1);
    directedGraph.addEdge(e2);
    directedGraph.addEdge(e3);

    //Count nodes and edges
    System.out.println("Nodes: "+directedGraph.getNodeCount()+" Edges: "+directedGraph.getEdgeCount());

    //Get a UndirectedGraph now and count edges
    UndirectedGraph undirectedGraph = graphModel.getUndirectedGraph();
    GraphView view = undirectedGraph.getView();

    System.out.println("Edges: "+undirectedGraph.getEdgeCount());   //The mutual edge is automatically merged

    //Iterate over nodes
    for(Node n : directedGraph.getNodes()) {
        Node[] neighbors = directedGraph.getNeighbors(n).toArray();
        System.out.println(n.getNodeData().getLabel()+" has "+neighbors.length+" neighbors");
    }

    //Iterate over edges
    for(Edge e : directedGraph.getEdges()) {
        System.out.println(e.getSource().getNodeData().getId()+" -> "+e.getTarget().getNodeData().getId());
    }

    //Find node by id
    Node node2 = directedGraph.getNode("n2");

    //Get degree
    System.out.println("Node2 degree: "+directedGraph.getDegree(node2));

    //Preview configuration
    PreviewController previewController = Lookup.getDefault().lookup(PreviewController.class);
    PreviewModel previewModel = previewController.getModel();

    previewModel.getProperties().putValue(PreviewProperty.SHOW_NODE_LABELS, Boolean.FALSE);
    previewModel.getProperties().putValue(PreviewProperty.NODE_LABEL_COLOR, new DependantOriginalColor(Color.WHITE));
    previewModel.getProperties().putValue(PreviewProperty.EDGE_CURVED, Boolean.FALSE);
    previewModel.getProperties().putValue(PreviewProperty.EDGE_OPACITY, 50);
    previewModel.getProperties().putValue(PreviewProperty.EDGE_RADIUS, 10f);
    previewModel.getProperties().putValue(PreviewProperty.BACKGROUND_COLOR, Color.BLACK);
    previewController.refreshPreview();

    //New Processing target, get the PApplet
    ProcessingTarget target = (ProcessingTarget) previewController.getRenderTarget(RenderTarget.PROCESSING_TARGET);
    PApplet applet = target.getApplet();
    applet.init();
    //Refresh the preview and reset the zoom
    previewController.render(target);
    target.refresh();
    target.resetZoom();

    //Add the applet to a JFrame and display
    JFrame frame = new JFrame("Test Preview");
    frame.setLayout(new BorderLayout());

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.add(applet, BorderLayout.CENTER);

    frame.pack();
    frame.setVisible(true);
}

public static void main(String[] args) {
    TestGraph previewJFrame = new TestGraph();
    previewJFrame.script();
}
}

鼠标侦听器替代:

import org.gephi.graph.api.Graph;
import org.gephi.graph.api.GraphModel;
import org.gephi.graph.api.Node;
import org.gephi.graph.api.NodeData;
import org.gephi.graph.api.NodeIterable;
import org.gephi.graph.api.NodeIterator;
import org.gephi.preview.api.PreviewModel;
import org.gephi.preview.api.PreviewMouseEvent;
import org.gephi.preview.api.PreviewProperties;
import org.gephi.preview.spi.PreviewMouseListener;
import org.gephi.project.api.Workspace;
import org.openide.util.Lookup;
import org.openide.util.lookup.ServiceProvider;

/**
 *
 * @author ksexton
 */
@ServiceProvider(service = PreviewMouseListener.class)
public class MyMouseListener implements PreviewMouseListener {

public void mouseClicked(PreviewMouseEvent event, PreviewProperties properties, Workspace workspace) {
    System.out.println("(" + event.x + "," + event.y + ")");
    Lookup lookup = workspace.getLookup();
    GraphModel lookup1 = lookup.lookup(GraphModel.class);
    Graph graph = lookup1.getGraph();
    NodeIterable nodes = graph.getNodes();
    NodeIterator iterator = nodes.iterator();
    Node selectedNode = null;
    while (iterator.hasNext()) {
        Node next = iterator.next();
        NodeData nodeData = next.getNodeData();
        float x = nodeData.x();
        float y = -nodeData.y(); // event y is always wrong.
        float z = nodeData.z();
        float size = nodeData.getSize();
        final int minX = Math.round(x - size);
        final int maxX = Math.round(x + size);
        final int minY = Math.round(y - size);
        final int maxY = Math.round(y + size);
        System.out.println("(" + minX + "," + minY+")" + ", (" + maxX + "," + maxY+")");
        if (minX <= event.x && event.x <= maxX
                && minY <= event.y && event.y <= maxY) {
            selectedNode = next;
        }
    }
    if (selectedNode != null) {
        System.out.println("Found a Node!: (" + selectedNode.getNodeData().x()
                + "," + selectedNode.getNodeData().y() + ")");
    }
}

public void mousePressed(PreviewMouseEvent event, PreviewProperties properties, Workspace workspace) {
}

public void mouseDragged(PreviewMouseEvent event, PreviewProperties properties, Workspace workspace) {
}

public void mouseReleased(PreviewMouseEvent event, PreviewProperties properties, Workspace workspace) {
}
}

渲染器:

import org.gephi.preview.plugin.renderers.NodeRenderer;
import org.gephi.preview.spi.MouseResponsiveRenderer;
import org.gephi.preview.spi.PreviewMouseListener;
import org.gephi.preview.spi.Renderer;
import org.openide.util.lookup.ServiceProvider;

/**
 *
 * @author ksexton
 */
@ServiceProvider(service = Renderer.class)
public class NodeRenderer2 extends NodeRenderer implements MouseResponsiveRenderer {

public boolean needsPreviewMouseListener(PreviewMouseListener previewMouseListener) {
    return true;
}

}

如果有人有更好的,更不容易出错的方式,我想知道。

答案 1 :(得分:0)

实际上,您需要一个渲染才能使用PreviewMouseListener。 我认为这个话题对你有很大的帮助。顶部来自Gephi论坛。 不要忘记将MouseReseponsiveRenderer实现到渲染器。 在渲染方法中绘制绘画。