Search code examples
javaswinguser-interfacegraphicspaintcomponent

Drawing Multiple JComponents to a Frame


I am trying to draw multiple car objects onto the same window but it appears that they are overwriting each other.

Here is my overridden paintComponent method in the Car class

public void paintComponent(Graphics g) {
    Graphics2D g2 = (Graphics2D) g;

    g2.setColor(wheelColor);
    g2.fill(leftWheel);
    g2.fill(rightWheel);
    g2.setColor(bodyColor);
    g2.fill(body);
    g2.fill(cab);
}

And in my Viewer Class:

JFrame f = new JFrame();
initializeFrame(f);

Car x = new Car(100, 100);
Car y = new Car(300, 300);

f.add(x);
f.add(y);

Although the coordinates seem to be different, only the last car is being drawn.

Any suggestions? Thanks


Solution

  • What you want to do is use a data structure of Car objects and loop through them in the paintComonent method. Something like

    List<Car> cars = new ArrayList<>();
    ....
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        for (Car car : cars) {
            car.drawCar(g);
        }
    }
    

    The drawCar method would come from your Car class

    public class Car {
        int x, y;
        public Car(int x, int y) {
            this.x = x;
            this.y = y;
        }
    
        public void drawCar(Graphics g) {
            g.setColor(Color.BLACK);
            // do everything here as you would in a paintComponent method
        }
    }
    

    See more examples here and here and here and here and here and here.


    UPDATE

    Here is a simple example use some "Ferraris" I whipped up, also using some animation, but with the same basic points I have above.

    enter image description here

    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.util.ArrayList;
    import java.util.List;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    import javax.swing.Timer;
    
    public class DrawCar extends JPanel{
        private static final int D_W = 400;
        private static final int D_H = 400;
    
        List<Car> cars;
        public DrawCar() {
            cars = new ArrayList<>();
            cars.add(new Car(100, 300));
            cars.add(new Car(200, 100));
    
            Timer timer = new Timer(50, new ActionListener(){
                public void actionPerformed(ActionEvent e) {
                    for (Car car : cars) {
                        car.move();
                        repaint();
                    }
                }
            });
            timer.start();
        }
    
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            for (Car car : cars) {
                car.drawCar(g);
            }
        }
    
        @Override
        public Dimension getPreferredSize() {
            return new Dimension(D_W, D_H);
        }
    
        public class Car {
            private static final int INCREMENT = 5;
            int x, y;
            public Car(int x, int y) {
                this.x = x;
                this.y = y;
            }
            public void drawCar(Graphics g) {
                g.setColor(Color.BLUE);
                g.fillRect(x, y, 100, 30);
                g.setColor(Color.BLACK); // body
                g.fillOval(x + 15, y + 20, 15, 15); // wheel
                g.fillOval(x + 60, y + 20, 15, 15); // wheel
                g.fillRect(x + 15, y - 20, 60, 20); // top
            }
    
            public void move() {
                if (x == D_W) {
                    x = 0;
                } else {
                    x += INCREMENT;
                }
            }
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    JFrame frame = new JFrame();
                    frame.add(new DrawCar());
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    }