动态绘制树的问题

时间:2014-03-18 23:17:46

标签: java swing graphics tree paintcomponent

我已经找到了答案。一些指向正确方向的主题是:

How to draw a tree representing a graph of connected nodes? http://www.daniweb.com/software-development/java/threads/151175/drawing-tree-with-jframe

无论如何,这是问题所在。我需要能够使用没有第三方的东西将树绘制到JFrame中;只是摆动的方法。我的代码如下:我没有包含的Tree类,但它需要一个文本文件并将其解析为树结构。我遇到了两个问题:首先,我无法获得节点的值以显示在椭圆形中。该值存储为字符串,应该通过Node传递。其次,即使我覆盖了paintComponent,线也没有显示出来。有人可以帮忙吗?

NodeLabel:

public class NodeLabel extends JLabel{

public Node node;
public Point topConnection;
public Point bottomConnection;

public NodeLabel(Node _node){
    super(_node.value);
    node = _node;

    this.setText(node.value);
    this.add(new JLabel(node.value));
    topConnection = new Point(this.getWidth()/2, 0);
    bottomConnection = new Point(this.getWidth()/2, this.getHeight());
}


@Override
public void paintComponent(Graphics g){
    g.drawOval(5,  5,  25, 15);
}

DrawTree类:

private ArrayList<NodeLabel> nodes;
private Tree tree;
private NodeLabel root;
private int currentX;
private int currentY;

public DrawStuff(Tree _tree){
    tree = _tree;
    currentX = 40;
    currentY = 0;
    this.setLayout(null);
    this.setMinimumSize(new Dimension(300, 300));

    root = new NodeLabel(tree.root);
    root.setHorizontalAlignment(SwingConstants.CENTER);
    this.add(root);
    root.setBounds(currentX, currentY, currentX + 20, currentY + 25);
//      root.setLocation(currentX, currentY);



    currentX = currentX - 20;
    currentY = currentY + 30;

    for(Node node : tree.root.children){
        NodeLabel temp = new NodeLabel(node);
        this.add(temp);
        temp.setBounds(currentX, currentY, currentX +20, currentY + 25);
        this.add(drawEdge(this.getGraphics(), root, temp));

        temp.setLocation(currentX, currentY);
        currentX += 40;


        System.out.println("child added");
    }

}

private JPanel drawEdge(Graphics g, NodeLabel parent, NodeLabel child){     
    final Point p1 = parent.bottomConnection;
    final Point p2 = child.topConnection;

    JPanel line = new JPanel(){
        @Override
        public void paintComponent(Graphics g){
            super.paintComponent(g);
            g.drawLine(p1.x, p1.y, p2.x, p2.y);
        }
    };

    return line;
}

public static void main(String[] args) throws Exception{
    Tree tree = new Tree(args[0]);
    System.out.println(tree.toString());
    DrawStuff dTree = new DrawStuff(tree);
    dTree.setVisible(true);
}

树类:树采用格式良好的文件(几乎为xml)并将其存储在数据结构中。标签的形成如下:,嵌套标签显示层次结构。 IE:

public class Tree {

Node root;

/**
 * Tree constructor method
 * Takes the file and constructs a tree based on the contents
 * @param filename the name(or path) of the file to extract information from
 */
//Take the file and create all the nodes
public Tree(String filename) throws Exception{
    File file = new File(filename);
    Scanner s = new Scanner(file);

    Node current = new Node("x");
    if(s.hasNext()){
        s.next();
        String temp = s.next();
        String value = temp.substring(0, temp.length()-1);
        root = new Node(value);
        current = root;
    }
    while(s.hasNext()){
        String temp = s.next();
        if(temp.charAt(1) != '/'){ //then it is an open Tag.
            temp = s.next(); //this is our value + ">"
            String value = temp.substring(0, temp.length()-1);
            //create a new node with the value that's the child of our current node
            Node tempNode = current.addChild(value
                    );
            //current = the node we just created
            current = tempNode;     
        } else{
            if (current.parent!= null){
            current = current.parent;
            }
        }
    }
}

public String toString(){
    return root.toString();

}


public class Node{

    Node parent;
    ArrayList<Node> children;
    String value;

    public Node(String value){
        children = new ArrayList<Node>();
        this.value = value;
    }

    public Node(String value, Node parent){
        this.parent = parent;
        children = new ArrayList<Node>();
        this.value = value;
    }

    public Node addChild(String value){
        Node temp = new Node(value, this);
        this.children.add(temp);
        return temp;
    }

    public String toString(){
        String result = "";
        result += this.value + "\n"; 

        for(Node child:children){
            result += "    " + child.toString();
        }
        return result;
    }

}

}

1 个答案:

答案 0 :(得分:1)

我可以看到一些严重的问题。首先,不要使用多个组件以这种方式呈现不同的元素。而是创建一个能够呈现整个内容的自定义组件。这克服了你似乎不理解的坐标上下文问题......

首先从extends JLabel课程中移除NodeLabel,此类应该以某种方式drawable,以便您可以将Graphics上下文传递给它它会画自己。

创建一个TreePanel,其范围从JPanel开始。这将充当树的主要容器。提供一种可以设置树引用的方法。覆盖组件的paintComponent方法并将节点渲染到它,在你认为合适的情况下在它们之间绘制线条......

详细了解Performing Custom Painting2D Graphics了解详情