Java рисует движущиеся прямоугольники в цикле - PullRequest
0 голосов
/ 13 октября 2018

Мне нужно нарисовать прямоугольники AWT / Swing, которые перемещаются от кадра к кадру.

У меня есть Playground класс

public Playground(int sizeX, int sizeY)
{
    frame = new JFrame();
    frame.setVisible(true);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    panel = new JPanel();
    panel.setSize(sizeX, sizeY);
    panel.setDoubleBuffered(true);

    panel.setVisible(true);
    frame.add(panel);
    frame.pack();
    frame.setSize(sizeX, sizeY);
}

public void refresh()
{
    panel.repaint();
}

public Graphics getGraphics()
{
    return panel.getGraphics();
}

Это класс, в котором объекты должныбыть нарисованным:

public class Star {

    private static int size = 10;

    private int posX;
    private int posY;

    public Star(int posX, int posY)
    {
        this.posX = posX;
        this.posY = posY;
    }

    public void paint(Graphics g)
    {
        g.fillRect(posX, posY, size, size);
    }

    public int getPosX() {
        return posX;
    }

    public int getPosY() {
        return posY;
    }
}

Это основной метод:

public static void main(String[] args) {
    Playground playground = new Playground(400, 400);
    Star star = new Star(100, 100);
    Star star2 = new Star(125, 125);
    while(1 == 1)
    {
        playground.refresh();
        star.paint(playground.getGraphics());
        star2.paint(playground.getGraphics());
    }
}

Объекты нарисованы, но мерцают, как я могу остановить их мерцание?

Редактировать: Я решил мерцание для одного элемента, изменив метод обновления на:

public void refresh()
{
    panel.getGraphics().clearRect(0,0, panel.getWidth(), panel.getHeight());
}

К сожалению, только один элемент не мигает, все остальные все еще мерцают.

1 Ответ

0 голосов
/ 13 октября 2018

Ниже приведен однофайловый mcve, который демонстрирует перемещение (вращение для простоты) прямоугольника с помощью пользовательского рисования.Один файл означает, что вы можете скопировать и вставить весь код в один файл (AnimateRectangle.java) и выполнить его.Параметр

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

public class AnimateRectangle {

    private JFrame frame;

    public AnimateRectangle(Model model){

        frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JPanel panel = new MyJPanel(model);
        panel.setDoubleBuffered(true);

        frame.add(panel);
        frame.pack();
        frame.setVisible(true);
    }

    void refresh() {
        frame.repaint();
    }

    public static void main(String[] args) throws InterruptedException {
        Controller controller = new Controller(400, 400);
        while (true) {
            Thread.sleep(1000);
            SwingUtilities.invokeLater(()->controller.animate());
        }
    }
}

//"wires" gui and model 
class Controller{

    private Model model;
    private AnimateRectangle view;

    Controller(int sizeX, int sizeY){

         model = new Model(sizeX, sizeY);
         view = new AnimateRectangle(model);
    }

    void animate() {
        int newAngle = (model.getAngle() < 360 ) ? model.getAngle()+1 : 0 ;
        model.setAngle(newAngle);
        view.refresh();
    }
}

//represents the inforamtion the GUI needs 
class Model{

    int sizeX, sizeY, angle = 0;

    public Model(int sizeX, int sizeY) {
        this.sizeX = sizeX;
        this.sizeY = sizeY;
    }

    int getSizeX() { return sizeX; }

    int getSizeY() {return sizeY;}

    int getAngle() {return angle;}

    //degrees
    void setAngle(int angle) {  this.angle = angle; }
}

//a JPanel with custom paint component 
class MyJPanel extends JPanel {

    private Model model;

    public MyJPanel(Model model) {
        this.model = model;
        setPreferredSize(new Dimension(model.getSizeX(), model.getSizeY()));
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D)g;
        g2d.setColor(Color.RED);
        int sizeX = model.getSizeX(), sizeY = model.getSizeY();
        g2d.rotate(Math.toRadians(model.getAngle()), sizeX /2, sizeY/2);
        g2d.fillRect(sizeX/4, sizeY/4, sizeX/2, sizeY/2);
    }
}

A лучше (см. Комментарий camickr) предназначен для анимации с помощью свинга Timer .Для этого удалите метод animate() и замените его на:

void animateWithTimer(){

    new Timer(1000,new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent e) {
            int newAngle = (model.getAngle() < 360 ) ? model.getAngle()+1 : 0 ;
            model.setAngle(newAngle);
            view.refresh();
        }
    }).start();
}

и измените main, чтобы использовать его:

public static void main(String[] args) throws InterruptedException {
    Controller controller = new Controller(400, 400);
    controller.animateWithTimer();
}
...