3

我有一个模拟分布式环境的简单程序。我想通过使用 GraphStream 库来可视化处理器行为。每个处理器都是一个线程,他们做一些计算,但不是一直,只有当我设置switch变量时

while(running){
  if(switch)
    computate();
}

我写了一个类,它采用处理器列表并准备图形可视化。这个任务有一个功能

  public void adjustBFSGraph2(){
    for(Edge e: this.g.getEdgeSet())
    {
        e.clearAttributes();
    }
    try {
        Thread.sleep(2000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    for(Processor p : processorList)
    {
        p.getNode().setAttribute("ui.label", "Pid" +" " + p.getPID() +" "+"Dist: " + p.getFieldValue("bfs") + " " + "Parent" + " " + p.getFieldValue("parent"));
        if(!p.getFieldValue("parent").equals("-1"))
        {
            Edge e = p.getNode().getEdgeBetween(p.getFieldValue("parent"));
            if(e != null)
            {
                e.setAttribute("ui.color", p.getColor());
                e.setAttribute("ui.label", "added" + p.getPID());

            }
        }
    }
}

我的问题是我只在眨眼时看到边缘上的颜色,然后颜色消失。看起来它添加了属性"ui.color"并在同一个循环中将其删除,但它怎么可能呢?@update我已经编辑了我的代码,现在我可以看到thread.sleep()在第一个循环之后指定的时间边缘,我不明白为什么在清除所有属性后我实际上可以看到它们。这是我如何调用我的函数

    while(true)
            {   i++;
//if any processor is not runing
                boolean aux = false;
                while(!aux) {
                    for (Processor proc : s.processorList) {
                        aux = aux || proc.isEnabled();
                    }
                    aux = !aux;
                }
                s.gp.adjustBFSGraph();
                Thread.sleep(5000);
                for(Processor proc: s.processorList)
                {
                    proc.enable();
                }
            }

Thread.sleep()内部调整功能设置为小于 100 毫秒时,它会再次开始闪烁。

因为可能有点不清楚我在做什么,所以我创建了较小的示例

这相当于我的处理器类

    public class SomeObjectWithNode {
    public Node n;
    public Color c;
    public SomeObjectWithNode(Node n)
    {
        Random rand = new Random();
        float r = rand.nextFloat();
        float g = rand.nextFloat();
        float b = rand.nextFloat();
        Color randomColor = new Color(r, g, b);
        c = randomColor;
        this.n = n;
    }

}

这是一个类女巫改变图形样式/绘制它

    public class TestDraw {
    Vector<SomeObjectWithNode> n;
    Graph g;
    public TestDraw(Vector<SomeObjectWithNode> k, Graph g)
    {
        this.g= g;
        this.n = k;
    }
    public void adjust()
    {
        Random rand = new Random();
        for(Edge e: g.getEdgeSet())
        {
            e.clearAttributes();
        }
        for(SomeObjectWithNode k: n)
        {
            k.n.addAttribute("ui.color", k.c);
            for(Edge e: k.n.getEdgeSet())
            {
                float r = rand.nextFloat();
                float g = rand.nextFloat();
                float b = rand.nextFloat();
                Color randomColor = new Color(r, g, b);
                e.addAttribute("ui.color", randomColor);
            }
        }
    }
}

这是主要课程

public class TestGs {

        public static void main(String[] args) {
            Node lastNode;
            TestDraw t;
            Vector<SomeObjectWithNode> a = new Vector<SomeObjectWithNode>();
            System.setProperty("gs.ui.renderer", "org.graphstream.ui.j2dviewer.J2DGraphRenderer");
            Graph g = new SingleGraph("test1");
            g.display();
            g.addAttribute("ui.stylesheet", "node { fill-mode: dyn-plain; size: 10px;} edge { fill-mode: dyn-plain; size: 2px;}");
            a.add(new SomeObjectWithNode(g.addNode(Integer.toString(0))));
            lastNode = g.getNode("0");
            for(int i = 1; i < 10; i++)
            {
                a.add(new SomeObjectWithNode(g.addNode(Integer.toString(i))));
                g.addEdge(Integer.toString(i-1).concat(Integer.toString(i)), a.get(i).n, lastNode);
                lastNode = a.get(i).n;
            }
            t = new TestDraw(a,g);
            while(true)
            {
                t.adjust();
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }

        }

    }

当我运行示例时,我们可以看到图形仅具有眨眼的颜色,而不是显示它的时间Thread.sleep()

4

1 回答 1

1

主要问题在于e.clearAttributes();方法adjust()。您不仅删除了“ui.color”的所有属性。您可以e.setAttribute("ui.color", randomColor);改用e.addAttribute("ui.color", randomColor);e.clearAttributes()完全删除块(参见原始示例编号 2)。

我已经相应地修改了您的代码,并在gist.github上分享了它。现在它每 2 秒改变一次颜色。

PS:现在关于致盲的原因。我对 GraphStream 源代码进行了简短的调查(很多 java 代码,抱歉)。AbstractElement.java(只有有趣的方法):

    public void clearAttributes() {
            if (attributes != null) {
                for (Map.Entry<String, Object> entry : attributes.entrySet())
                    attributeChanged(AttributeChangeEvent.REMOVE, entry.getKey(),
                            entry.getValue(), null);

                attributes.clear();
            }
        }
...
    public void setAttribute(String attribute, Object... values) {
        addAttribute(attribute, values);
    }
...
    public void addAttribute(String attribute, Object... values) {
        if (attributes == null)
            attributes = new HashMap<String, Object>(1);

        Object oldValue;
        Object value;
        if (values.length == 0)
            value = true;
        else if (values.length == 1)
            value = values[0];
        else
            value = values;

        AttributeChangeEvent event = AttributeChangeEvent.ADD;
        if (attributes.containsKey(attribute)) // In case the value is null,
            event = AttributeChangeEvent.CHANGE; // but the attribute exists.

        oldValue = attributes.put(attribute, value);
        attributeChanged(event, attribute, oldValue, value);
    }
...

如您所见, setAttribute 和 addAttribute 非常相似。现在在 GraphicElement.java 中实现 attributeChanged():

@Override
    protected void attributeChanged(AttributeChangeEvent event,
            String attribute, Object oldValue, Object newValue) {
        if (event == AttributeChangeEvent.ADD
                || event == AttributeChangeEvent.CHANGE) {
            if (attribute.charAt(0) == 'u' && attribute.charAt(1) == 'i') {
                if (attribute.equals("ui.class")) {
                    mygraph.styleGroups.checkElementStyleGroup(this);
                    // mygraph.styleGroups.removeElement( tis );
                    // mygraph.styleGroups.addElement( this );
                    mygraph.graphChanged = true;
                } else if (attribute.equals("ui.label")) {
                    label = StyleConstants.convertLabel(newValue);
                    mygraph.graphChanged = true;
                } else if (attribute.equals("ui.style")) {
                    // Cascade the new style in the style sheet.

                    if (newValue instanceof String) {
                        try {
                            mygraph.styleSheet.parseStyleFromString(
                                    new Selector(getSelectorType(), getId(),
                                            null), (String) newValue);
                        } catch (Exception e) {
                            logger.log(Level.WARNING, String.format("Error while parsing style for %S '%s' :", getSelectorType(), getId()), e);
                        }
                        mygraph.graphChanged = true;
                    } else {
                        logger.warning("Unknown value for style [" + newValue + "].");
                    }
                } else if (attribute.equals("ui.hide")) {
                    hidden = true;
                    mygraph.graphChanged = true;
                } else if (attribute.equals("ui.clicked")) {
                    style.pushEventFor(this, "clicked");
                    mygraph.graphChanged = true;
                } else if (attribute.equals("ui.selected")) {
                    style.pushEventFor(this, "selected");
                    mygraph.graphChanged = true;
                } else if (attribute.equals("ui.color")) {
                    style.pushElementAsDynamic(this);
                    mygraph.graphChanged = true;
                } else if (attribute.equals("ui.size")) {
                    style.pushElementAsDynamic(this);
                    mygraph.graphChanged = true;
                } else if (attribute.equals("ui.icon")) {
                    mygraph.graphChanged = true;
                }
                // else if( attribute.equals( "ui.state" ) )
                // {
                // if( newValue == null )
                // state = null;
                // else if( newValue instanceof String )
                // state = (String) newValue;
                // }
            } else if (attribute.equals("label")) {
                label = StyleConstants.convertLabel(newValue);
                mygraph.graphChanged = true;
            }
        } else // REMOVE
        {
            if (attribute.charAt(0) == 'u' && attribute.charAt(1) == 'i') {
                if (attribute.equals("ui.class")) {
                    Object o = attributes.remove("ui.class"); // Not yet removed
                                                                // at
                                                                // this point !
                    mygraph.styleGroups.checkElementStyleGroup(this);
                    attributes.put("ui.class", o);
                    mygraph.graphChanged = true;
                } else if (attribute.equals("ui.label")) {
                    label = "";
                    mygraph.graphChanged = true;
                } else if (attribute.equals("ui.hide")) {
                    hidden = false;
                    mygraph.graphChanged = true;
                } else if (attribute.equals("ui.clicked")) {
                    style.popEventFor(this, "clicked");
                    mygraph.graphChanged = true;
                } else if (attribute.equals("ui.selected")) {
                    style.popEventFor(this, "selected");
                    mygraph.graphChanged = true;
                } else if (attribute.equals("ui.color")) {
                    style.popElementAsDynamic(this);
                    mygraph.graphChanged = true;
                } else if (attribute.equals("ui.size")) {
                    style.popElementAsDynamic(this);
                    mygraph.graphChanged = true;
                }
            } else if (attribute.equals("label")) {
                label = "";
                mygraph.graphChanged = true;
            }
        }
    }

注意:正如您在清除属性时所看到的,动态样式将通过方法添加/删除popElementAsDynamic/pushElementAsDynamic。并在 StyleGroup.java 中实现这些方法:

     /**
     * Indicate the element has dynamic values and thus cannot be drawn in bulk
     * operations. Called by the GraphicElement.
     * 
     * @param element
     *            The element.
     */
    protected void pushElementAsDynamic(Element element) {
        if (dynamicOnes == null)
            dynamicOnes = new HashSet<Element>();

        dynamicOnes.add(element);
    }

    /**
     * Indicate the element has no more dynamic values and can be drawn in bulk
     * operations. Called by the GraphicElement.
     * 
     * @param element
     *            The element.
     */
    protected void popElementAsDynamic(Element element) {
        dynamicOnes.remove(element);

        if (dynamicOnes.isEmpty())
            dynamicOnes = null;
    }

好吧,当我们添加/setAttribute 时,我们只在现有的 hashmap 中添加新元素。当我们使用 clearAttributes 时,我们会为 HashMap 创建新实例dynamicOnes。可能在这种情况下,我们有同步问题,这就是闪烁的原因。

于 2016-05-12T21:24:38.893 回答