Draw lines in graphical representation of binary tree

I am trying to draw a binary tree using swing and awt in java. I can already show the nodes of the tree but I am not able to draw the lines of a parent node to its children. I have the node, TreeGUI, DrawTree and Main classes. This image is how the output is without the lines.

Binary tree

My intention is to show rows from a parent node to its child nodes. I tried using method drawLine of Class Graphics but it got like this:

Tree

The drawTree method sets the position of the values of the nodes on the screen and saves the position of the nodes in ArrayLists. The drawLine method draws the lines. I believe the rows are that way because the values are saved in that particular order. I've tried several ways and I can't connect the lines correctly. How can I show only one parent's lines to their children?

public class TreeGUI extends JFrame {

    private JPanel contentPane;
    public Node node;
    public DrawTree drawer;

    /**
     * Create the frame.
     */
    public TreeGUI(Node node) {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 500, 500);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        contentPane.setLayout(new BorderLayout(0, 0));
        drawer = new DrawTree(node);
        contentPane.add(drawer);
        setContentPane(contentPane);
        this.node = node;
        setVisible(true);
    }

}

class DrawTree extends JPanel{

    public Node node;
    public static ArrayList listX = new ArrayList();
    public static ArrayList listY = new ArrayList();


    public DrawTree(Node node){
        this.node = node;
    }

    @Override
    protected void paintComponent(Graphics g) {
        // TODO Auto-generated method stub
        g.setFont(new Font("Tahoma", Font.BOLD, 20));
        DrawTree(g, 0, getWidth(), 0, getHeight() / node.getheight(node), node);
        listX.clear();
        listY.clear();
    }

    public void DrawTree(Graphics g, int StartWidth, int EndWidth, int StartHeight, int Level, Node node) {
        String data = String.valueOf(node.getValue());
        g.setFont(new Font("Tahoma", Font.BOLD, 20));
        FontMetrics fm = g.getFontMetrics();
        int dataWidth = fm.stringWidth(data);

        g.drawString(data, (StartWidth + EndWidth) / 2 - dataWidth / 2, StartHeight + Level / 2);
        listX.add((StartWidth + EndWidth) / 2 - dataWidth / 2);
        listY.add(StartHeight + Level / 2);
        drawLine(g, node);

        if (node.getLeft() != null) {
            DrawTree(g, StartWidth, (StartWidth + EndWidth) / 2, StartHeight + Level, Level, node.getLeft());
        }
        if (node.getRight() != null)
            DrawTree(g, (StartWidth + EndWidth) / 2, EndWidth, StartHeight + Level, Level, node.getRight());
    }

public void drawLine(Graphics g,  Node node){
       for (int i=1; i < listY.size(); i++)
            g.drawLine((int)listX.get(i-1), (int)listY.get(i-1), (int)listX.get(i), (int)listY.get(i));
    }

}

Main method

public static void main(String[] args) {
    Node raiz = null;
    raiz = raiz.insert(raiz, 35);
    raiz.insert(raiz, 25);
    raiz.insert(raiz, 75);
    raiz.insert(raiz, 30);
    raiz.insert(raiz, 20);
    raiz.insert(raiz, 12);
    raiz.insert(raiz, 6);
    raiz.insert(raiz, 23);
    raiz.insert(raiz, 90);
    TreeGUI gui = new TreeGUI(raiz);
}
Author: Bruno Brito, 2016-05-27

1 answers

Try with these modifications I made, it will probably work, I tested with a Tree class that I had already implemented and it worked, I hope I helped.

public void DrawTree(Graphics g, int StartWidth, int EndWidth, int StartHeight, int Level, Node node) {
    String data = String.valueOf(node.getValue());
    g.setFont(new Font("Tahoma", Font.BOLD, 20));
    FontMetrics fm = g.getFontMetrics();
    int dataWidth = fm.stringWidth(data);

    g.drawString(data, (StartWidth + EndWidth) / 2 - dataWidth / 2, StartHeight + Level / 2);
    listX.add((StartWidth + EndWidth) / 2 - dataWidth / 2);
    listY.add(StartHeight + Level / 2);
    drawLine(g, node);

    //Imprime as linhas que ligam os nós a seus filhos
    if(listX.size() > 1){
        g.drawLine((int)listX.get(listX.size()-2), (int)listY.get(listY.size()-2), (int)listX.get(listX.size()-1), (int)listY.get(listY.size()-1));
    }

    if (node.getLeft() != null) {
        DrawTree(g, StartWidth, (StartWidth + EndWidth) / 2, StartHeight + Level, Level, node.getLeft());
    }

    if (node.getRight() != null){

         /*Como a recursão visita os nós da esquerda primeiro, se o nó que está sendo tratado for o filho à direira e
            houver filho(s) à esquerda, quer dizer que os filhos à esquerda já foram visitados e suas linhas já foram 
            desenhadas, ou seja, seus pontos devem ser removidos, para evitar que sejam desenhados outra vez. 
         */
        if (listX.size() > 1 && node.getLeft() != null) {
            for(int i = 0; i < node.getLeft().getHeight(); i++){
                listX.remove(listX.size()-1);
                listY.remove(listY.size()-1);
            }
        }
        DrawTree(g, (StartWidth + EndWidth) / 2, EndWidth, StartHeight + Level, Level, node.getRight());
    }
}
 1
Author: Carlos Emídio, 2017-05-25 18:04:08