Java 图形可视化
我有一个模拟分布式环境的简单程序。我想通过使用GraphStream库来可视化处理器行为。每个处理器都是一个线程,它们会进行一些计算,但并非总是这样,只有在我设置Java 图形可视化,java,multithreading,graph,graphstream,Java,Multithreading,Graph,Graphstream,我有一个模拟分布式环境的简单程序。我想通过使用GraphStream库来可视化处理器行为。每个处理器都是一个线程,它们会进行一些计算,但并非总是这样,只有在我设置开关变量时才会这样做 while(running){ if(switch) computate(); } 我已经写了一个类,它采用processorList并准备图形可视化。 此任务有一个函数 public void adjustBFSGraph2(){ for(Edge e: this.g.getEdgeSe
开关变量时才会这样做
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()
internal adjust函数设置为小于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);
}
}
}
}
公共类TestDraw{
向量n;
图g;
公共测试图(向量k,图g)
{
这个.g=g;
这个,n=k;
}
公共空间调整()
{
Random rand=新的Random();
对于(边,例如:getEdgeSet())
{
e、 clearAttributes();
}
对于(节点为k:n的SomeObjectWithNode)
{
k、 n.addAttribute(“ui.color”,k.c.);
对于(边e:k.n.getEdgeSet())
{
float r=rand.nextFloat();
float g=rand.nextFloat();
float b=rand.nextFloat();
颜色随机性颜色=新颜色(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();
}
}
}
}
公共类TestGs{
公共静态void main(字符串[]args){
节点lastNode;
TestDraw t;
向量a=新向量();
setProperty(“gs.ui.renderer”、“org.graphstream.ui.j2dviewer.J2DGraphRenderer”);
图g=新的单图(“test1”);
g、 显示();
g、 addAttribute(“ui.stylesheet”,“节点{填充模式:dyn平原;大小:10px;}边缘{填充模式:dyn平原;大小:2px;}”);
a、 添加(新的SomeObjectWithNode(g.addNode(Integer.toString(0))));
lastNode=g.getNode(“0”);
对于(int i=1;i<10;i++)
{
a、 添加(新的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=新的测试图(a,g);
while(true)
{
t、 调整();
试一试{
睡眠(3000);
}捕捉(中断异常e){
//TODO自动生成的捕捉块
e、 printStackTrace();
}
}
}
}
当我运行这个示例时,我们可以看到图形只有眨眼的时候才有颜色,而不是在Thread.sleep()
中显示时间。主要问题是e.clearAttributes()方法adjust()
中的code>。您将删除所有属性,而不仅仅是“ui.color”。您可以使用e.setAttribute(“ui.color”,randomColor)代码>而不是e.addAttribute(“ui.color”,randomColor)编码>并用e.clearAttributes()
完全删除块(参见原始编号2)。
我已经相应地修改了您的代码,并在上分享了我的评论。现在它每2秒改变一次颜色。
PS:现在谈谈暴动的原因。我对GraphStream源代码进行了简短的调查(很抱歉,有很多java代码)。
AbstractElement.java(仅有趣的方法):
注意:正如您在清除属性时所看到的,动态样式将通过方法poplementasdynamic/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;
}
/**
*指示元素具有动态值,因此无法批量绘制
*行动。由GraphicElement调用。
*
*@param元素
*元素。
*/
受保护的空心pushElementAsDynamic(图元){
如果(dynamicOnes==null)
dynamicOnes=newhashset();
dynamicOnes.add(元素);
}
/**
*指示该元素不再具有动态值,并且可以批量绘制
*行动。由GraphicElement调用。
*
*@param元素
*元素。
*/
受保护的void popElementAsDynamic(元素){
动态锥。移除(元件);
if(dynamicOnes.isEmpty())
dynamicOnes=null;
}
当我们添加/setAttribute时,我们只在已有的hashmap中添加新元素。当我们使用clearAttributes时,我们为dynamicOnes
创建新的实例HashMap。可能在这种情况下,我们出现了同步问题,这就是导致闪烁的原因。您那边有什么意见吗?我已经更正了我的答案,希望这就是您想要的我接受它,但它没有说明为什么删除属性并在以后添加它们会导致闪烁effect@whd已添加PS部件,请检查
@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;
}
}
}
/**
* 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;
}