Search code examples
javagraphicsgraphics2d

G2D updating with lists of coordinates


I want to make a program to simulate ants.Let's say I have 100 ants and every one of them has coordinates (2 integers). I use the Java Graphics (Graphics2D).

Now I want a class that reads a list like that:

List<List<Integer>> list = new ArrayList();

This list has for example:

[100,200],[200,100]

as coordinates in it. Now I want the class to update al the time and delete all "dots" (ants) and after that draw them new with the coordinates out of the List.

Right now this won't work.

public class FrameHandler {

Panel panel  = new Panel();

public FrameHandler() {
    //initialize frame
    frame.repaint();

    List<List<Integer>> test = new ArrayList();
    List<Integer> t1 = new ArrayList();
    t1.add(100);
    t1.add(200);
    test.add(gunther);

    frame.add(panel);

    panel.setList(test);

    //the thread sleeps for 5 seconds

    List<Integer> t2 = new ArrayList();
    t2.add(100);
    t2.add(100);
    test.add(gunther2);

    panel.removeAll();

    panel.setList(olaf);
}


public void setList(List<Integer> list) {
    panel.setList(list);
}

public void setSize(int width, int height) {
    frame.setSize(width, height);
}

private class Panel extends JPanel {

    List<List<Integer>> antList = new ArrayList();

    private void doDrawing(Graphics g) {

        Graphics2D g2d = (Graphics2D) g;

        for(int i = 0; i < antList.size(); i++) {
            g2d.fillRect(antList.get(i).get(0), antList.get(i).get(1), 2, 2);
        }
    }

    @Override
    public void paintComponent(Graphics g) {

        super.paintComponent(g);
        doDrawing(g);
    }

    public void setList(List<List<Integer>> list) {
        antList = list;
    }
}

}

If you have another idea how to solve the problem, maybe with an API or another method of doing graphics I would be happy to hear it.


Solution

  • Now I want the class to update al the time and delete all "dots" (ants) and after that draw them new with the coordinates out of the List.

    This is basically how painting works in Swing, on each paint cycle, you are expected to repaint the entire state of the component from scratch. See Painting in AWT and Swing for more details.

    So the question becomes, how do you update the List. While there are a number ways you might do this, using a Swing Timer might be the simplest (and generally the safest). See How to use Swing Timers for more details.

    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Random;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.Timer;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    
    public class FrameHandler {
    
        public static void main(String[] args) {
            new FrameHandler();
        }
    
        public FrameHandler() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                        ex.printStackTrace();
                    }
    
                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public static class TestPane extends JPanel {
    
            protected static final Random RANDOM_DELTA = new Random();
    
            private List<List<Integer>> ants;
    
            public TestPane() {
                Random rnd = new Random();
                ants = new ArrayList<>(25);
                for (int index = 0; index < 10; index++) {
                    List<Integer> ant = new ArrayList<>(2);
                    // You should also have a look at the java.awt.Point class :P
                    ant.add(rnd.nextInt(200 - 2)); //x
                    ant.add(rnd.nextInt(200 - 2)); //y
                    ants.add(ant);
                }
    
                Timer timer = new Timer(40, new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
    
                        for (List<Integer> ant : ants) {
                            int xDelta = randomDelta();
                            int yDelta = randomDelta();
    
                            int x = ant.get(0) + xDelta;
                            int y = ant.get(1) + yDelta;
    
                            if (x < 0) {
                                x = 0;
                            } else if (x + 2 > getWidth()) {
                                x = getWidth() - 2;
                            }
                            if (y < 0) {
                                y = 0;
                            } else if (y + 2 > getHeight()) {
                                y = getHeight() - 2;
                            }
    
                            ant.set(0, x);
                            ant.set(1, y);
                        }
                        repaint();
    
                    }
                });
                timer.start();
            }
    
            protected int randomDelta() {
                int delta = 0;
                do {
                    double rnd = Math.random();
                    delta = rnd < 0.5d ? -1 : 1;
                } while (delta == 0);
                return delta;
            }
    
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(200, 200);
            }
    
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                Graphics2D g2d = (Graphics2D) g.create();
                for (List<Integer> ant : ants) {
                    g2d.fillRect(ant.get(0), ant.get(1), 2, 2);
                }
                g2d.dispose();
            }
    
        }
    
    }
    

    This example basically generates a random delta (change in direction) for each ant's x & y coordinate. I suspect you might need to have something a little more sophisticated