图形可视化



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

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

我已经写了一个类,它采用processorList并准备图形可视化。此任务有一个功能

  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"并将其删除,但这怎么可能呢?@更新我已经编辑了我的代码,现在我可以在第一次循环后在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()内部调节功能设置为小于100ms时,它再次开始闪烁。

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

这相当于我的处理器类

    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() 中显示时间。

主要问题是方法adjust()中的e.clearAttributes();。您不仅可以删除"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时,我们为dynamicOnes创建了新的实例HashMap。在这种情况下,我们可能会出现同步问题,这就是闪烁的原因。

相关内容

  • 没有找到相关文章

最新更新