mardi 4 août 2015

How can I animate my binary tree drawing in Java

I am really struggling with a a project that I am working on. The eventual outcome should be an animation that shows algorithms in AVLTrees. I have managed to display a tree using values input by a user. But I am worried that they I have done it may prevent me being able to animate it. Each time a node is added, the entire tree is re drawn (up to a depth of four at the moment), is there a way (I assume after a lot of "if" statements) do gradually animate the new line added, and then have the new node appear? I apologise in advance if this is the worst code ever seen on here, I"m very new to java and struggling a lot!

    package dissV12;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class AnimateNode implements ActionListener {

    NodePane nodePane = new NodePane();
    JButton jb1, jb2, jb3;  
    JTextField tf;

    public static void main(String[] args) {

        AnimateNode animate = new AnimateNode();

    }

    public AnimateNode() {

        JFrame frame = new JFrame("Version12");     
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new BorderLayout());

        JPanel jp1 = new JPanel();      

        tf = new JTextField(3);
        jb1 = new JButton("Search");
        jb2 = new JButton("Insert");
        jb3 = new JButton("Delete");
        jb1.addActionListener(this);
        jb2.addActionListener(this);
        jb3.addActionListener(this);
        frame.add(jp1, BorderLayout.SOUTH);
        jp1.add(tf);
        jp1.add(jb1);
        jp1.add(jb2);
        jp1.add(jb3);

        nodePane.setPreferredSize(new Dimension(1000, 600));
        frame.add(nodePane, BorderLayout.CENTER);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        String input = tf.getText();
        int numbInput = (int) ((Double.parseDouble(input)));

        if (e.getSource() == jb1) {

            tf.setText("");
        }

        if (e.getSource() == jb2) {
            nodePane.insert(numbInput);
            tf.setText("");

        }

        if (e.getSource() == jb3) {

            tf.setText("");

        }

    }

}

This next class is where the drawing takes place. So I assume this is where I put the timer??? Beyond that, I have no idea what I'm doing but feel I have read everything on the internet :/

import java.awt.FontMetrics;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Random;

import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.Timer;


public class NodePane extends JPanel implements ActionListener {

    private Timer t;

    AVLTree12<Integer> tree;
    Node adding;

    public NodePane() {
        tree = new AVLTree12<Integer>();
        adding = null;
        t = new Timer(1000, this);
        t.start();
    }

    public void addingNode(Node n) {
        adding = n;
    }

    public void insert(int n) {
        tree.insert(n);
        tree.updateLevels();        
        Node nd = tree.getNodeSearch(n);
        System.out.println(nd);
        addingNode(nd);
        repaint();
    }

    public void delete(int n){
        if(tree.search(n)){

        }
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2D = (Graphics2D) g.create();
        if (adding != null) {

            Queue<Node> queue = new LinkedList<Node>();
            queue.add(tree.root);

            while (!queue.isEmpty()) {
                Node node = queue.poll();
                int level = node.getLevel();
                if (level == 1) {
                    Point p = paintLevelOne(node, g2D);
                    paintNode(node, p, g2D);
                }

                if (level == 2) {
                    Node parent = node.getParent();
                    if (node.compareTo(parent) > 0) {
                        Point p = paintLevelTwo(node, 2, g2D);
                        paintLine(node, g2D);
                        paintNode(node, p, g2D);
                    }
                    if (node.compareTo(parent) < 0) {
                        Point p = paintLevelTwo(node, 1, g2D);
                        paintLine(node, g2D);
                        paintNode(node, p, g2D);
                    }
                }
                if (level == 3) {
                    Node parent = node.getParent();
                    Node gParent = parent.getParent();
                    if (node.compareTo(parent) < 0 && parent.compareTo(gParent) < 0) {
                        Point p = paintLevelThree(node, 1, g2D);
                        paintLine(node, g2D);
                        paintNode(node, p, g2D);

                    }
                    if (node.compareTo(parent) > 0 && parent.compareTo(gParent) < 0) {
                        Point p = paintLevelThree(node, 2, g2D);
                        paintLine(node, g2D);
                        paintNode(node, p, g2D);

                    }
                    if (node.compareTo(parent) < 0 && parent.compareTo(gParent) > 0) {
                        Point p = paintLevelThree(node, 3, g2D);
                        paintLine(node, g2D);
                        paintNode(node, p, g2D);

                    }
                    if (node.compareTo(parent) > 0 && parent.compareTo(gParent) > 0) {
                        Point p = paintLevelThree(node, 4, g2D);
                        paintLine(node, g2D);
                        paintNode(node, p, g2D);

                    }

                }
                if(level == 4){
                    Node parent = node.getParent();
                    Node gParent = parent.getParent();
                    Node gGParent = gParent.getParent();
                    if (node.compareTo(parent) < 0 && parent.compareTo(gParent) < 0 && gParent.compareTo(gGParent)<0) {
                        Point p = paintLevelFour(node, 1, g2D);
                        paintLine(node, g2D);
                        paintNode(node, p, g2D);

                    }
                    if (node.compareTo(parent) > 0 && parent.compareTo(gParent) < 0 && gParent.compareTo(gGParent)<0) {
                        Point p = paintLevelFour(node, 2, g2D);
                        paintLine(node, g2D);
                        paintNode(node, p, g2D);

                    }
                    if (node.compareTo(parent) < 0 && parent.compareTo(gParent) > 0 && gParent.compareTo(gGParent)<0) {
                        Point p = paintLevelFour(node, 3, g2D);
                        paintLine(node, g2D);
                        paintNode(node, p, g2D);

                    }
                    if (node.compareTo(parent) > 0 && parent.compareTo(gParent) > 0 && gParent.compareTo(gGParent)<0){
                        Point p = paintLevelFour(node, 4, g2D);
                        paintLine(node, g2D);
                        paintNode(node, p, g2D);

                    }
                    if (node.compareTo(parent) < 0 && parent.compareTo(gParent) < 0 && gParent.compareTo(gGParent)>0) {
                        Point p = paintLevelFour(node, 5, g2D);
                        paintLine(node, g2D);
                        paintNode(node, p, g2D);

                    }
                    if (node.compareTo(parent) > 0 && parent.compareTo(gParent) < 0 && gParent.compareTo(gGParent)>0) {
                        Point p = paintLevelFour(node, 6, g2D);
                        paintLine(node, g2D);
                        paintNode(node, p, g2D);

                    }
                    if (node.compareTo(parent) < 0 && parent.compareTo(gParent) > 0 && gParent.compareTo(gGParent)>0) {
                        Point p = paintLevelFour(node, 7, g2D);
                        paintLine(node, g2D);
                        paintNode(node, p, g2D);

                    }
                    if (node.compareTo(parent) > 0 && parent.compareTo(gParent) > 0 && gParent.compareTo(gGParent)>0){
                        Point p = paintLevelFour(node, 8, g2D);
                        paintLine(node, g2D);
                        paintNode(node, p, g2D);

                    }
                }
                Node left = node.getLeft();
                Node right = node.getRight();
                if (left != null) {
                    queue.add(left);
                }
                if (right != null) {
                    queue.add(right);
                }
            }
        }

    }

    public void paintNode(Node n, Point p, Graphics2D g2d) {

        if (n != null) {

            FontMetrics fm = g2d.getFontMetrics();
            int radius = (fm.getHeight()) * 2;

            Ellipse2D circ = new Ellipse2D.Float(p.x, p.y, radius, radius);
            g2d.draw(circ);
            String text = String.valueOf(n.getData());
            int xTextPos = p.x + ((radius - fm.stringWidth(text)) / 2);
            int yTextPos = p.y
                    + (((radius - fm.getHeight()) / 2) + fm.getAscent());

            g2d.drawString(text, xTextPos, yTextPos);
        }
    }

    public void paintLine(Node n, Graphics2D g2d) {
        FontMetrics fm = g2d.getFontMetrics();
        int radius = (fm.getHeight()) * 2;
        Node parent = n.getParent();
        Point p = parent.getLocation();
        int xPar = p.x + (radius/2);
        int yPar = p.y + radius;
        Point pP = new Point(xPar, yPar);

        Point pc = n.getLocation();
        int xC = pc.x+(radius/2);
        int yC = pc.y;
        Point pC = new Point(xC, yC);
        g2d.draw(new Line2D.Float(pP, pC));

    }

    public Point paintLevelOne(Node n, Graphics2D g2d) {
        FontMetrics fm = g2d.getFontMetrics();
        int radius = (fm.getHeight()) * 2;
        int x = (getWidth() / 2) - (radius / 2);
        int y = radius;
        Point p = new Point(x, y);
        n.setLocation(p);
        return p;
    }

    public Point paintLevelTwo(Node n, int l2, Graphics2D g2d) {
        FontMetrics fm = g2d.getFontMetrics();
        int radius = (fm.getHeight()) * 2;
        int x = (l2 * (getWidth() / 3)) - (radius / 2);
        int y = 3 * radius;
        Point p = new Point(x, y);
        n.setLocation(p);
        return p;
    }

    public Point paintLevelThree(Node n, int l3, Graphics g2d) {
        FontMetrics fm = g2d.getFontMetrics();
        int radius = (fm.getHeight()) * 2;
        int x = (l3 * (getWidth() / 5)) - (radius / 2);
        int y = 5 * radius;
        Point p = new Point(x, y);
        n.setLocation(p);
        return p;
    }

    public Point paintLevelFour(Node n, int l4, Graphics g2d){
        FontMetrics fm = g2d.getFontMetrics();
        int radius = (fm.getHeight()) * 2;
        int x = (l4 * (getWidth() / 9)) - (radius / 2);
        int y = 8 * radius;
        Point p = new Point(x, y);
        n.setLocation(p);
        return p;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        // TODO Auto-generated method stub

    }

}

I assume I won't need to show the Node Class and the Tree class.

If anyone can help I would cry much appreciate it :)

Aucun commentaire:

Enregistrer un commentaire