Как прикрепить AttributeChangedListener к графику из Graphstream?

#java #events #graphstream

#java #Мероприятия #graphstream

Вопрос:

Мне нужно со временем изменять атрибуты узлов и ребер. Время разбивается на временные периоды, каждый временной период выглядит одинаково: проверьте каждый узел и ребро на предмет возможных изменений и отредактируйте атрибут при необходимости. В частности, существуют числовые атрибуты, а размер узла и ширина ребра основаны на значении атрибутов. Изначально график отображается правильно. Узлы и ребра имеют предполагаемый размер. Но динамическое изменение значений атрибута с течением времени не приводит к изменению размеров элементов. Как я могу убедиться, что изменения атрибута также изменяют визуализацию графиков?

Насколько я понимаю, в документах и руководствах Graphstream есть источники, приемники и каналы (канал является как источником, так и приемником). Источники создают события, приемники их потребляют. Я использую GridGenerator, который является источником. Я могу добавить график в качестве приемника и позволить генератору создать график. Я думаю, тогда мне нужно добавить приемник к графику, потому что изменение атрибутов элементов графика делает его источником. Но что я использую в качестве приемника? graph.display() возвращает средство просмотра, но я не могу добавить его в качестве приемника, в нем говорится, что он несовместим с аргументами для graph.addSink(sink) . Несмотря на то, что в документах Graphstream говорится, что средство просмотра является приемником и что средство просмотра автоматически добавляется в качестве приемника. Почему тогда я не вижу изменений в пользовательском интерфейсе? Я не понимаю.

После генерации графика узлы и ребра получают там атрибуты

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

Кто-нибудь знает, как мне добавить приемник? Или я что-то еще упускаю?

Комментарии:

1. Я допустил ошибку. Дополнительная информация здесь .

Ответ №1:

Во-первых, у вас может быть ViewerPipe с вашим viewer таким образом :

 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;" 
            "}";
}
  

Вы можете найти пример здесь в graphstream 2.0 swing, здесь в graphstream 2.0 javafx или здесь в graphstream 1.3 (в scala).

Комментарии:

1. Хотя это хороший ответ, он не добавляет слушателя к событиям атрибута узла. Я хотел бы знать, как добавить прослушиватель, когда установлены атрибуты, в частности, атрибут «ui.selected».