2013-06-19 49 views
0

我試圖遞歸地將樹的所有節點繪製到JPanel上。Java - 在JPanel上繪製樹節點

它應該是這樣的:

enter image description here

其中,BCD,是A孩子。

而且,EFB

孩子的父子關係的輸出是準確的:

PARENT: A | x,y: 180, 100... 
CHILD: B | x,y: 205, 150 
PARENT: B | x,y: 205, 150... 
CHILD: E | x,y: 230, 200 
PARENT: B | x,y: 205, 150... 
CHILD: F | x,y: 230, 200 
end 
PARENT: A | x,y: 180, 100... 
CHILD: C | x,y: 205, 150 
PARENT: A | x,y: 180, 100... 
CHILD: D | x,y: 205, 150 

x, y座標不是......每個孩子的x位置重疊的其他孩子的...所以它只顯示每個父代有1個子節點:

enter image description here

我認爲我必須做的是找到一種方法,每增加一行兒童就增加一次y ...併爲每位父母的每個孩子增加x,這樣他們就可以很好地放在單行上了......但是,座標正在重置。

有什麼想法?

代碼:

public void paintComponent(Graphics g) { 
    g.setColor(Color.BLACK); 
    g.fillRect(0, 0, width, height); 
    g.setColor(Color.CYAN); 
    g.fillRect(rootNode.getX(), rootNode.getY(), rootNode.getWidth(), rootNode.getHeight()); 
    paintComponent(g, rootNode); 

} 

public void paintComponent(Graphics g, Nodes parentNode) { 
    //keep generating new nodePrintList to load with new Children 
    ArrayList<Nodes> nodePrintList = new ArrayList<Nodes>();  

    //base case: end of nodeList 
    if (nodeList.indexOf(parentNode)==nodeList.size()-1) { 
     System.out.println("\nend"); 
    } 
    else { 
    //traverse nodeList recursively 
     nodePrintList = getChildren(parentNode);  
     //loop through and print all children of node n 
     System.out.println(); 

     for (Nodes child : nodePrintList) {    
      g.setColor(Color.GREEN); 
      child.setX(parentNode.getX()+25); 
      child.setY(parentNode.getY()+50); 
      g.fillRect(child.getX(), child.getY(), child.getWidth(), child.getHeight()); 
      System.out.print("PARENT: " + parentNode.getValue() + " | x,y: " + parentNode.getX() + ", " + parentNode.getY() + "...\n CHILD: " + child.getValue() + " | x,y: " + child.getX() + ", " + child.getY());  
      paintComponent(g, child); 
     }   
    } 
} 

getChildren()方法返回每單親家庭子女名單:

//need to pass a new index to getChildren once current node has no more children 
public ArrayList<Nodes> getChildren (Nodes n) { 
    ArrayList<Nodes> childrenList; 
    childrenList = new ArrayList<Nodes>(); 
    int index = nodeList.indexOf(n); 
    int col = 0; 

    while (col < size) { 
     if (adjMatrix[index][col] == 1) { 
      childrenList.add(nodeList.get(col)); 
     } 
     col++; 
    } 
    return childrenList; 
} 
+1

佈局有點複雜......如果在你的例子'C'中有孩子呢?它們會與'B'的重疊。 –

+0

@tobias_k好的,那麼你知道我可以遞歸地繪製樹的節點嗎? – Growler

回答

2

主要問題似乎是在你paintComponent方法for循環。在這裏,您爲每個孩子使用相同的x座標。你可以這樣修復:

int x = parentNode.getX()+25; // x position of first child 
for (Nodes child : nodePrintList) { 
    child.setX(x); 
    child.setY(parentNode.getY()+50); // y position is same for each child 
    // [...] fill rect, print, recursive call, etc. 
    x -= 50; // in each iteration, move nodes further to the left 
} 

但是,這只是一個問題。另一個問題是,爲了正確佈置節點,您必須考慮每個分支的總寬度。解決這個問題的一種方法是返回每個分支的總寬度,讓paintComponent(g, nodes)返回x,併爲下一個孩子使用這個(加上一些偏移量)。上面的代碼可能看起來像這樣:

int x = parentNode.getX()+25; // x position of first child 
for (Nodes child : nodePrintList) { 
    child.setX(x); 
    child.setY(parentNode.getY()+50); // y position is same for each child 
    // [...] fill rect, print, etc. 
    x = paintComponent(g, child) - 50; // next x is left of the total width of the child 
} 
return x; // return x (change methods signature accordingly) 

這可能仍然需要一些修補程序,但它應該給你的想法。

+0

我希望自己能想出這些解決方案......我只是被卡住了!非常感謝! – Growler

+0

另外,如何解決每個分支的總寬度的下一個問題?這將成爲一個程序,人們可以將節點添加到父級...因此每個分支需要動態寬度 – Growler

2

的問題就在這裏:

for (Nodes child : nodePrintList) {    
    //... 
    child.setX(parentNode.getX()+25); 
    //... 
} 

你的程序代碼總是子節點的位置設置爲一個固定的x和從父Ÿ距離,不管是哪個節點。

一種解決方法:

for (int idx = 0; idx < nodePrintList.size(); idx++) { 
    Nodes node = nodePrintList.get(idx);    
    //... 
    child.setX(parentNode.getX()+ 25 * ((float)(nodePrintList.size()-1)/2 - idx); 
    //... 
} 

雖然我的數學可能有點過,這應該同樣空間中的所有孩子家長直屬節點,從下每25個單位了。