Рисование нескольких J-компонентов в кадр

Я пытаюсь нарисовать несколько автомобильных объектов в одном окне, но кажется, что они перезаписывают друг друга.

Вот мой переопределенный метод paintComponent в классе Car

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);
}

И в моем классе зрителя:

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

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

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

Хотя координаты кажутся разными, разрисовывается только последний автомобиль.

Какие-либо предложения? Спасибо

2 ответа

Решение

То, что вы хотите сделать, это использовать структуру данных Car объекты и перебирать их в paintComonent метод. Что-то вроде

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

drawCar метод будет исходить из вашего Car учебный класс

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
    }
}

Смотрите больше примеров здесь и здесь, и здесь, и здесь, и здесь, и здесь.


ОБНОВИТЬ

Вот простой пример использования некоторого "Феррари", который я выбрал, также используя некоторую анимацию, но с теми же базовыми пунктами, которые у меня были выше.

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);
            }
        });
    }
}

но похоже, что они перезаписывают друг друга.

Менеджер по умолчанию для JFrame - BorderLayout. Таким образом, по умолчанию вы добавляете все свои компоненты в ЦЕНТР BorderLayout. Тем не менее, вы можете добавить в CENTER только один компонент, чтобы отображался только последний автомобиль.

Измените Layout Manager на FlowLayout, чтобы увидеть разницу.

Или, похоже, вы пытаетесь раскрасить Автомобили в случайных положениях, и в этом случае вы должны использовать "нулевую" компоновку. Тогда вы будете нести ответственность за установку размера / расположения каждого из компонентов автомобиля.

Другие вопросы по тегам