java - 如何将 AttributeChangedListener 从 Graphstream 附加到图表?

标签 java events graphstream

我需要随着时间的推移更改节点和边的属性。时间被分成时间段,每个时间段看起来都一样:检查每个节点和边是否有可能的更改,并在必要时编辑属性。具体来说,有数字属性,节点的大小和边的宽度基于属性值。最初,图表显示正确。节点和边具有假定的大小。但随着时间的推移动态更改属性值不会改变元素大小。我如何确保属性更改也会更改图形可视化?

据我了解 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;

这是 graphstream 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;"+
            "}";
}

你可以找到一个例子here在 graphstream 2.0 swing 中,here在 graphstream 2.0 javafx 或 here 中在 graphstream 1.3 中(在 scala 中)。

关于java - 如何将 AttributeChangedListener 从 Graphstream 附加到图表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55794651/

相关文章:

javascript - 输入按钮 onclick 事件未触发

java - 检索连接的组件 Graphstream

java - 用户异常 : Attempt to open odb database file that is currently in use by another process

java - 为什么复制对象不会影响第一个对象?

java - Spring Boot 2.4.0 版本中 CORS 策略的更改

php - 在谷歌日历中插入事件

vba - 从自定义集合类中的对象引发事件

java - 图的可视化

java - 使用工具包将图形流式传输到 Gephi : NullPointerException

java - Jenkins 未通过 gradle 测试任务,找不到导入文件