Java绘制循环中的移动矩形

时间:2018-10-13 11:31:58

标签: java swing awt drawing

我需要绘制逐帧移动的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 :(得分:1)

以下是一个单文件mcve,它演示了如何通过自定义绘制移动(为简单起见旋转)矩形。 一个文件意味着您可以将整个代码复制粘贴到一个文件(AnimateRectangle.java)中并执行它。

as.formula

更好选项(请参见camickr注释)是使用挥杆动作Timer进行动画处理。为此,请删除tibble方法,然后将其替换为:

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

并更改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();
}