[英]Java drawing moving rectangles in loop
I need to draw in AWT/Swing rectangles that are moving from frame to frame.我需要绘制从帧到帧移动的 AWT/Swing 矩形。
I have a Playground
class我有一个
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();
}
This is the class in which objects should be drawn:这是应该在其中绘制对象的类:
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;
}
}
This is the main method:这是主要方法:
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());
}
}
The objects are drawn but are flickering, how can I stop it from flickering?对象已绘制但闪烁,如何阻止它闪烁?
Edit: I solved the flickering for one element, by changing the refresh method to:编辑:我通过将刷新方法更改为:
public void refresh()
{
panel.getGraphics().clearRect(0,0, panel.getWidth(), panel.getHeight());
}
Unfortunately only one Element is not flickering all others are still flickering.不幸的是,只有一个元素不闪烁,所有其他元素仍在闪烁。
The following is a one-file mcve that demonstrates moving (rotating for simplicity) a rectangle by custom painting.下面是一个单文件 mcve,它演示了通过自定义绘制移动(为简单起见旋转)矩形。 One-file meaning that you can copy-paste the entire code into one file (AnimateRectangle.java) and execute it.
一个文件意味着您可以将整个代码复制粘贴到一个文件 (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 better option (see camickr comment) is to animate using swing Timer .更好的选择(参见 camickr 评论)是使用 swing Timer动画。 To do so, remove
animate()
method, and replace it with :为此,请删除
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();
}
and change main
to use it :并更改
main
以使用它:
public static void main(String[] args) throws InterruptedException {
Controller controller = new Controller(400, 400);
controller.animateWithTimer();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.