2012-04-04 50 views
1

我有一個prefuse應用程序,用於加載GraphML文件,其中節點具有「Color」字符串屬性。即。GraphML節點着色Prefuse

<node id="1"> 
    <data key="Color">Green</data> 
<node> 

我想允許指定一系列預定義的顏色,我不希望強制創建該GraphML使用所有的顏色方案。

我認爲這將是一個簡單的任務(也許它是?),但prefuse似乎在任何時候都打我。我已經提出了兩個部分解決方案,但他們都有他們的問題。我的第一種方法是手動添加到「顏色」的字符串相關的新的整數屬性,就像這樣:

// Add new property to Graph g 
g.addColumn("ColorNumber", int.class); 

// Add property to each node 
Iterator<Node> it = g.nodes(); 
while(it.hasNext()) { 
    Node n = it.next(); 
    String type = n.getString("Color"); 
    // Compare to an array of accepted types 
    for(int i=0; i < colorMap.length; i++) { 
     if(type.equalsIgnoreCase(colorMap[i])) { 
      n.setInt("ColorNumber", i); 
      break; 
     } 
    } 
} 

然後,您可以使用prefuse的默認顏色經理將這些整數鏈接到數組索引。

draw.add(new DataColorAction("graph.nodes", "ColorNumber", Constants.NUMERICAL, VisualItem.FILLCOLOR, fillArray)); 

這種方法的最大問題(最重要的是不雅觀)是,當用戶指定的顏色少於三種時,它會失敗。如果指定了兩種顏色,prefuse將使用顏色數組的第一個和最後一個元素。如果一個,第一個。咩。

我的另一個解決方案是手動設置每個節點的顏色。

// Iterate over VisualItems in Visualization vis 
Iterator<VisualItem> v_it = vis.items("graph.nodes"); 
while(v_it.hasNext()) { 
    VisualItem item = v_it.next(); 
    String type = item.getString("Color"); 
    for(int i=0; i < typeMap.length; i++) { 
     if(type.equalsIgnoreCase(typeMap[i])) { 
      item.setFillColor(fill[i]); 
      item.setEndFillColor(fill[i]); 
      break; 
     } 
    } 
} 
vis.repaint(); 

這適用於任何數量的顏色,但隨機混亂起來。我認爲prefuse在自己的線程上處理這些方法,由於某種原因,它運行緩慢。對於較小的網絡,我可以設置一個固定的等待時間(我沒有找到使用Thread.join()方法)。但是,對於大型網絡來說,這會失敗(閱讀:崩潰我的電腦)。

所以,你有它。不必要的大量時間承擔這項微不足道的任務。有人設法完成這個?有沒有簡單的方法?請告訴我,我正在推翻這一點。

回答

1

我知道prefuse這樣的經歷非常好: -/

第一種方法是在正確的道路,但指定了錯誤的數據類型。顏色是一個NOMINAL變量。

DataColorAction color = new DataColorAction("graph.nodes", "Color", 
    Constants.NOMINAL, VisualItem.FILLCOLOR, fillArray); 

ColorNumber字段是沒有必要的。

您對第二種方法的結論是正確的。 prefuse在一個單獨的線程中運行其ActionList。因此不應該手動設置視覺屬性。

如果需要更細粒度的代碼,則可以擴展DataColorAction

+0

擴展DataColorAction是我最終選擇的解決方案。另外,我需要更好地瞭解StackOverflow問題。 – PattimusPrime 2012-04-27 22:49:52