AbdelKh
AbdelKh

Reputation: 542

Display Prefuse Node field

I want to display a simple Graph with nodes IDs inside Nodes using Prefuse but this seems to be more complicated than it sounds.

Graph g = new Graph();
for (int i = 0; i < 3; ++i) {
    Node n1 = g.addNode();
    n1.setInt("label", 1); // I am trying to add a field in a node
    Node n2 = g.addNode();
    Node n3 = g.addNode();
    g.addEdge(n1, n2);
    g.addEdge(n1, n3);
    g.addEdge(n2, n3);
}
g.addEdge(0, 3);
g.addEdge(3, 6);
g.addEdge(6, 0);

// add visual data groups
VisualGraph vg = m_vis.addGraph(GRAPH, g);
m_vis.setInteractive(EDGES, null, false);
m_vis.setValue(NODES, null, VisualItem.SHAPE, new Integer(Constants.SHAPE_STAR));

However, it seems that this field doesn't exist, it makes sense since I didn't add this field but there isn't an option to add a field neither. I am getting this exception referring to the n1.setInt("DEFAULT_NODE_KEY", 1) line:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
    at java.util.ArrayList.elementData(Unknown Source)
    at java.util.ArrayList.get(Unknown Source)
    at prefuse.data.Table.getColumn(Table.java:457)
    at prefuse.data.Table.setInt(Table.java:1032)
    at prefuse.data.tuple.TableTuple.setInt(TableTuple.java:215)
    at prefuse.demos.AggregateDemo.initDataGroups(AggregateDemo.java:141)
    at prefuse.demos.AggregateDemo.<init>(AggregateDemo.java:72)
    at prefuse.demos.AggregateDemo.demo(AggregateDemo.java:182)
    at prefuse.demos.AggregateDemo.main(AggregateDemo.java:176)

I am not sure how to use fields in Nodes. I tried to read the library's help but I don't manage to figure that out.

Upvotes: 1

Views: 241

Answers (1)

trashgod
trashgod

Reputation: 205785

You may be looking for a LabelRenderer. In the example below, a LabelRenderer is constructed in such a way as to render nodes having the label GraphLib.LABEL, defined as "label":

LabelRenderer r = new LabelRenderer(GraphLib.LABEL);

The nodes comprising the Graph are given text via setString() using the same key, GraphLib.LABEL. For example, the root Node added to the Graph returned by GraphLib.getDiamondTree() is assigned the key GraphLib.LABEL and the value "0,0".

Node r = t.addRoot();
r.setString(LABEL, "0,0");

Later, when the Visualization runs, the renderer attempts to use text from the GraphLib.LABEL field.

image

import java.awt.Dimension;
import javax.swing.JFrame;
import prefuse.Display;
import prefuse.Visualization;
import prefuse.action.ActionList;
import prefuse.action.RepaintAction;
import prefuse.action.assignment.ColorAction;
import prefuse.action.layout.graph.ForceDirectedLayout;
import prefuse.activity.Activity;
import prefuse.controls.DragControl;
import prefuse.controls.PanControl;
import prefuse.controls.ZoomControl;
import prefuse.data.Graph;
import prefuse.render.DefaultRendererFactory;
import prefuse.render.LabelRenderer;
import prefuse.util.ColorLib;
import prefuse.util.GraphLib;
import prefuse.visual.VisualItem;

/** @see https://stackoverflow.com/a/44274886/230513 */
public class Example {

    private static final int W = 640;
    private static final int H = 480;

    public static void main(String[] argv) {

        // -- 1. create the data ------------------------------------------------
        Graph graph = GraphLib.getDiamondTree(3, 2, 1);

        // -- 2. the visualization --------------------------------------------
        // add the graph to the visualization as the data group "graph"
        // nodes and edges are accessible as "graph.nodes" and "graph.edges"
        Visualization vis = new Visualization();
        vis.add("graph", graph);
        vis.setInteractive("graph.edges", null, false);

        // -- 3. the renderers and renderer factory ---------------------------
        LabelRenderer r = new LabelRenderer(GraphLib.LABEL);
        r.setRoundedCorner(8, 8); // round the corners

        // create a new default renderer factory
        // return our name label renderer as the default for all non-EdgeItems
        // includes straight line edges for EdgeItems by default
        vis.setRendererFactory(new DefaultRendererFactory(r));

        // -- 4. the processing actions ---------------------------------------
        ColorAction fill = new ColorAction("graph.nodes",
            VisualItem.FILLCOLOR, ColorLib.rgb(200, 200, 255));
        // use black for node text
        ColorAction text = new ColorAction("graph.nodes",
            VisualItem.TEXTCOLOR, ColorLib.gray(0));
        // use light grey for edges
        ColorAction edges = new ColorAction("graph.edges",
            VisualItem.STROKECOLOR, ColorLib.gray(200));

        // create an action list containing all color assignments
        ActionList color = new ActionList();
        color.add(fill);
        color.add(text);
        color.add(edges);

        // create an action list with an animated layout
        ActionList layout = new ActionList(Activity.INFINITY);
        layout.add(new ForceDirectedLayout("graph"));
        layout.add(new RepaintAction());

        // add the actions to the visualization
        vis.putAction("color", color);
        vis.putAction("layout", layout);

        // -- 5. the display and interactive controls -------------------------
        Display d = new Display(vis) {

            @Override
            public Dimension getPreferredSize() {
                return new Dimension(W, H);
            }
        };
        d.setSize(W, H); // set display size
        d.pan(W / 2, H / 2); // pan to center
        d.addControlListener(new DragControl());
        d.addControlListener(new PanControl());
        d.addControlListener(new ZoomControl());

        // -- 6. launch the visualization -------------------------------------
        JFrame frame = new JFrame("prefuse label example");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(d);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true); // show the window

        vis.run("color");
        vis.run("layout");
    }
}

Upvotes: 1

Related Questions