简体   繁体   English

Java-将树节点绘制到JPanel上

[英]Java - Paint tree nodes onto JPanel

I'm trying to paint all nodes of a tree onto a JPanel recursively. 我试图递归地将树的所有节点绘制到JPanel上。

It should look like this: 它看起来应该像这样:

在此处输入图片说明

Where, B , C , D , are children of A . 其中BCDA子代。

And, E , F are children of B 而且, EFB子代

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: 但是x, y坐标不是...每个孩子的x位置与另一个孩子的x位置重叠...因此,每个父对象仅显示1个孩子节点:

在此处输入图片说明

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. 我想我要做的就是找到一种方法,每增加一行新的孩子就增加y ...,然后为父母的每个孩子增加x ,这样他们就可以很好地躺在一行上了。 。

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: 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;
}

The main problem seems to be in the for loop in your paintComponent method. 主要问题似乎在paintComponent方法的for循环中。 Here, you are using the same x coordinate for each children. 在这里,您为每个孩子使用相同的x坐标。 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. 解决此问题的一种方法是返回每个分支的总宽度,使paintComponent(g, nodes)返回x ,并将其(加上一些偏移量)用于下一个子级。 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. 这可能仍需要进行一些修改,但是应该可以给您带来启发。

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. 程序代码始终将子节点的位置设置为与父节点的x和y固定距离,而不管它在哪个节点上。

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. 虽然我的数学可能有一点偏差,但这应该将所有子节点平均放置在父节点的正下方,每一个节点距离下一个节点25个单位。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM