Как иметь простые анимированные фигуры, которые не меняют цвет на Java Swing? - PullRequest
0 голосов
/ 30 сентября 2019

У меня есть некоторый код, который я написал для забавы, который рисует линии кругов разными цветами. Без использования Swing Timer круги нарисованы «все сразу», и они чередуют цвет между красным, зеленым, синим и желтым. Итак, без таймера код работает как положено. Однако, когда я пытаюсь анимировать так, чтобы я мог видеть нарисованные круги, что означает использование таймера качания для цикла вместо цикла while / for, все круги имеют одинаковый цвет и продолжают мигать вместе четырьмя цветами. Я предполагаю, что проблема в том, что цвет связан не с каждым объектом, а со всем кадром, так как я меняю цвет рамки каждые несколько миллисекунд. Круги, которые уже нарисованы, не остаются с их первоначальным цветом, как это было свремя цикла. Если вы видите какое-либо решение для этого, помощь будет принята с благодарностью! Вот код:

public class Board extends JPanel {

    private static final long serialVersionUID = 6676924870723702476L;

    private Timer timer;
    private final int DELAY = 30;

    private ActionListener drawLine;
    private Ellipse2D circ;
    private ArrayList<Ellipse2D> circles = new ArrayList<>();

    private double circDiam = 80;
    private double circX = 0;
    private double circY = 0;
    private short circNum = 1;

    public Board() {

        drawLine = (ActionEvent e) -> {

            repaint();

            circX += circDiam;

            if(circNum == 5)
            {
                circNum = 1;            
            }
        };

        timer = new Timer(DELAY, drawLine);
        timer.start();
    }

    private Color getCircColor(short circNum) { 
        switch(circNum) {
            case 1:
                return Color.blue;
            case 2:
                return Color.red;
            case 3:
                return Color.yellow;
            case 4:
                return Color.green;
            default:
                return Color.gray;
        }
    }

    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        Dimension size = new Dimension(getWidth(), getHeight());
        double width = size.getWidth();
        double height = size.getHeight();

        Graphics2D g2d = (Graphics2D) g;

        RenderingHints rHints = new  RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        rHints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
        g2d.setRenderingHints(rHints);

        if(circX >= width - circDiam)
        {
            circY += circDiam;
            circX = 0;
            circDiam *= 0.865   ;
        }

        if(circY >= height - circDiam) {
            timer.stop();
        }

        circ = new Ellipse2D.Double(circX, circY, circDiam, circDiam);
        g2d.setColor(getCircColor(circNum));
        circNum++;
        circles.add(circ);

        for(Ellipse2D circ : circles) {
            g2d.fill(circ);
        }
    }

}

public class Execute extends JFrame {

    private static final long serialVersionUID = -3483390877436935589L;

    public Execute() {

        add(new Board());

        setSize(800, 800);
        setResizable(false);

        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }

    public static void main(String[] args) {

        EventQueue.invokeLater(() -> {
            Execute ex = new Execute();
            ex.setVisible(true);
        });
    }
}

Ответы [ 2 ]

2 голосов
/ 30 сентября 2019

Метод покраски только для покраски. НЕ должно:

  1. создавать объекты. То есть не создавайте свои объекты Circle.
  2. остановите Timer.
  3. код рисования будет просто перебирать ArrayList для рисования всех объектов Cirlce.

ActionListener Timer используется для:

  1. создания объектов Cirlce и добавления их в ArrayList по одному за раз.
  2. определяетЦвет каждого объекта
  3. остановить таймер, когда будет создано нужное количество объектов.

Так что в основном в вашем классе Board вам нужен метод, подобный addCircle(....). Это добавит объект Circle в ArrayList и затем вызовет repaint() для себя. Затем вы изменяете код ActionListener, чтобы создать объект Circle, и вызываете метод addCirle(...).

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

Верный. Вам понадобится нестандартный объект для рисования. Этот пользовательский объект будет содержать два свойства:

  1. объект Circle
  2. объект Color of Circle.

Или другой вариант - рисовать напрямуюв BufferedImage, а затем просто отобразить BufferedImage на панели.

См. Пользовательские подходы к рисованию для примера обоих этих подходов к рисованию.

0 голосов
/ 01 октября 2019

Хорошо, я сделал все, что сказал @camickr, я получил тот же результат, но за исключением вот код:

public class Board extends JPanel {

    private static final long serialVersionUID = 6676924870723702476L;

    private Timer timer;
    private final int DELAY = 30;

    private ActionListener drawLine;
    private RCircle circ;
    private ArrayList<RCircle> circles = new ArrayList<>();

    private double circDiam = 80;
    private double circX = 0;
    private double circY = 0;
    private short circNum = 1;

    private double height = 800;
    private double width = 800;

    public Board() {

        drawLine = (ActionEvent e) -> {

            if(circX >= width - circDiam)
            {
                circY += circDiam;
                circX = 0;
                circDiam *= 0.865   ;
            }

            if(circY >= height - circDiam) {
                timer.stop();
            }

            circ = new RCircle(circX, circY, circDiam, circNum);

            circNum++;

            addCircle();

            circX += circDiam;

            if(circNum == 5)
            {
                circNum = 1;            
            }
        };

        timer = new Timer(DELAY, drawLine);
        timer.start();
    }

    private void addCircle() {
        circles.add(circ);

        repaint();
    }

    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        Graphics2D g2d = (Graphics2D) g;

        RenderingHints rHints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        rHints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
        g2d.setRenderingHints(rHints);

        g2d.setColor(circ.getColor());

        for(RCircle circ : circles) {
            g2d.fill(circ.getCirc());
        }
    }

}


public class RCircle {

    private Ellipse2D circ;
    private Color color;

    public RCircle(double x, double y, double circDiam, short circNum) {
         this.circ = new Ellipse2D.Double(x, y, circDiam, circDiam);

         this.color = getCircColor(circNum);
    }

    private Color getCircColor(short circNum) { 
        switch(circNum) {
            case 1:
                return Color.blue;
            case 2:
                return Color.red;
            case 3:
                return Color.yellow;
            case 4:
                return Color.green;
            default:
                return Color.gray;
        }
    }

    public Ellipse2D getCirc() {
        return circ;
    }

    public void setCirc(Ellipse2D circ) {
        this.circ = circ;
    }

    public Color getColor() {
        return color;
    }

    public void setColor(Color color) {
        this.color = color;
    }

}


public class Execute extends JFrame {

    private static final long serialVersionUID = -3483390877436935589L;

    public Execute() {

        add(new Board());

        setSize(800, 800);
        setResizable(false);

        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }

    public static void main(String[] args) {

        EventQueue.invokeLater(() -> {
            Execute ex = new Execute();
            ex.setVisible(true);
        });
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...