我需要随着时间的推移更改节点和边的属性。时间分为多个时间段,每个时间段看起来都一样:检查每个节点和边缘是否有可能的更改,并在必要时编辑属性。具体来说,存在数值属性,节点的大小和边的宽度基于属性值。最初,图形显示正确。节点和边具有假定的大小。但是,随时间动态更改属性值不会更改元素大小。如何确保属性更改也会更改图形可视化?
据我了解 Graphstream 文档和教程,有源、汇和槽(管道既是源又是水槽)。源创建事件,接收器使用它们。我使用GridGenerator,这是一个来源。我可以将图形添加为接收器,并让生成器创建图形。我想,我必须向图形添加一个接收器,因为更改图形元素的属性使其成为源。但是我用什么作为水槽?graph.display()
返回一个查看器,但我无法将其添加为接收器,它说它与graph.addSink(sink)
的参数不兼容。即使 Graphstream 文档说查看器是一个接收器,并且查看器会自动添加为接收器。那为什么我在 UI 中看不到更改?我不明白。
生成图形后,节点和边将获得属性
public static void configureElements(Graph world) {
for (Node node : world.getEachNode()) {
double random = Math.random() * 100;
if (random < 20) {
// remove obstacles
world.removeNode(node)
} else if (random < 30) {
// node have rohstoffe
node.addAttribute("ui.class", "rohstoff");
node.addAttribute("ui.label", node.getId());
node.addAttribute("isRohstoff");
int capacity = (int) (Math.random() * maxCapacity);
node.addAttribute("capacity", capacity);ity);
// nodes size is based on capacity of rohstoffe
node.setAttribute("ui.size", node.getNumber("capacity") + 10);
} else if (random < 32) {
// node is a lager
node.addAttribute("ui.class", "lager");
node.addAttribute("ui.label", node.getId());
node.addAttribute("isLager");
node.addAttribute("lagerstand", 0);
// nodes size is based on capacity of the lager
node.setAttribute("ui.size", node.getNumber("lagerstand") + 10);
} else {
// normal node
node.addAttribute("isNode");
}
}
for (Edge edge : world.getEachEdge()) {
// add pheromones to edge
edge.addAttribute("pheromones", 0);
// edges size is based on number of pheromones
edge.setAttribute("ui.size", edge.getNumber("pheromones"));
}
}
在这里,我随时间动态更改节点属性
public void dropRohstoff(Node node) {
int oldRohstoff = (int) node.getNumber("rohstoff");
int newRohstoff = oldRohstoff++;
node.setAttribute("rohstoff", newRohstoff);
world.nodeAttributeChanged(world.getId(), (long) world.getStep(), node.getId(),"rohstoff", oldRohstoff, newRohstoff);
}
public void pickRohstoff(Node node) {
int oldCapacity = (int) node.getNumber("capacity");
int newCapicity = oldCapacity++;
node.setAttribute("capacity", newCapicity);
world.nodeAttributeChanged(world.getId(), (long) world.getStep(), node.getId(), "capacity", oldCapacity, newCapicity);
}
这里的边缘属性
public void evaporateAll() {
for (Edge edge : world.getEachEdge()) {
Double oldEvaporateRate = edge.getNumber("pheromones");
Double newEvaporateRate = oldEvaporateRate * (1.0 - evaporateRate);
edge.setAttribute("pheromones", newEvaporateRate);
world.edgeAttributeChanged(world.getId(), (long) world.getStep(), edge.getId(), "pheromones", oldEvaporateRate, newEvaporateRate);
}
}
有人知道我必须如何添加水槽吗?还是我错过了别的东西?
首先,你可以像这样拥有一个带有查看器的 ViewerPipe:
ViewerPipe pipeIn = viewer.newViewerPipe();
有了它,您可以向图形添加一个接收器:
pipeIn.addAttributeSink( graph );
pipeIn.pump();
另外,如果你想做一个动态大小,不要忘记将css属性添加到你的节点:
size-mode: dyn-size;
下面是图形流 1.3 的最小示例
public class Issue {
public static void main(String args[]) {
System.setProperty( "org.graphstream.ui.renderer", "org.graphstream.ui.j2dviewer.J2DGraphRenderer" );
new Issue();
}
protected boolean loop = true;
public Issue() {
Graph graph = new MultiGraph("main graph");
Viewer viewer = new Viewer(graph, Viewer.ThreadingModel.GRAPH_IN_ANOTHER_THREAD);
ViewerPipe pipeIn = viewer.newViewerPipe();
viewer.addView("view1", new J2DGraphRenderer());
graph.addAttribute("ui.antialias");
pipeIn.addAttributeSink( graph );
pipeIn.pump();
Node A = graph.addNode("A");
Node B = graph.addNode("B");
Node C = graph.addNode("C");
graph.addEdge("AB", "A", "B", true);
graph.addEdge("BC", "B", "C", true);
graph.addEdge("CA", "C", "A", true);
A.addAttribute("xyz", 0, 1, 0);
B.addAttribute("xyz", 1, 0, 0);
C.addAttribute("xyz", -1, 0, 0);
A.setAttribute("ui.label", "A");
B.setAttribute("ui.label", "B");
C.setAttribute("ui.label", "C");
graph.addAttribute("ui.stylesheet", styleSheet);
float color = 0;
float dir = 0.01f;
float size = 20f;
float sizeInc = 1f;
while( loop ) {
pipeIn.pump();
sleep( 40 );
A.setAttribute( "ui.size", size );
size += sizeInc;
if( size > 50 ) {
sizeInc = -1f; size = 50f;
} else if( size < 20 ) {
sizeInc = 1f; size = 20f;
}
System.out.println(size);
}
System.exit(0);
}
protected void sleep( long ms ) {
try { Thread.sleep( ms ) ; }
catch (InterruptedException e) { e.printStackTrace(); }
}
private String styleSheet =
"graph {"+
" canvas-color: white;"+
" fill-mode: gradient-radial;"+
" fill-color: white, #EEEEEE;"+
" padding: 60px;"+
" }"+
"node {"+
" size-mode: dyn-size;"+
" shape: circle;"+
" size: 20px;"+
" fill-mode: plain;"+
" fill-color: #CCC;"+
" stroke-mode: plain;"+
" stroke-color: black;"+
" stroke-width: 1px;"+
"}";
}
你可以在graphstream 2.0 swing,graphstream 2.0 javafx或graphstream 1.3(scala)中找到一个例子。