Reputation: 12718
I'm trying to paint all nodes of a tree onto a JPanel recursively.
It should look like this:
Where, B
, C
, D
, are children of A
.
And, E
, F
are children of B
The output of parent child relationship is accurate:
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
But the x, y
coordinates are not... Each child's x
location overlaps the other child's... so it only shows 1 child node per parent:
I think what I have to do is find a way to increment y
once per new row of children... and increment x
for each child of a parent so they lay nicely on a single row... But the nodes' coordinates are resetting.
Any thoughts?
Code:
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()
method to return list of children per parent:
//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;
}
Upvotes: 0
Views: 957
Reputation: 82929
The main problem seems to be in the for
loop in your paintComponent
method. Here, you are using the same x coordinate for each children. You could fix it like this:
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
}
However, this is just one problem. Another issue is, that for properly laying out the nodes, you have to take into account the total width of each branch. One way to fix this could be to return the total width of each branch, have paintComponent(g, nodes)
return x
, and use this (plus some offset) for the next child. The above code could then look somewhat like this:
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)
This probably still needs some tinkering, but it should give you the idea.
Upvotes: 2
Reputation: 4165
The problem is right here:
for (Nodes child : nodePrintList) {
//...
child.setX(parentNode.getX()+25);
//...
}
Your program code is always setting the child node's position to a fixed x and y distance from the parent, regardless of which node it is.
One solution to this:
for (int idx = 0; idx < nodePrintList.size(); idx++) {
Nodes node = nodePrintList.get(idx);
//...
child.setX(parentNode.getX()+ 25 * ((float)(nodePrintList.size()-1)/2 - idx);
//...
}
While my math may be a little off, this should equally space all the child nodes directly under the parent, each 25 units away from the next.
Upvotes: 2