我正在阅读一本(过时的)Java书,并且该项目应该“动画化”在屏幕上移动的一个圆。但是,运行该程序时,圆仍保留在一个位置。我的代码看起来与本书相同。我忘记了什么吗?我在错误的时间致电repaint()吗?
public class Animation
{
JFrame f;
int x, y;
public static void main(String [] args)
{
Animation a = new Animation();
a.go();
}
public void go()
{
f=new JFrame();
myPanel p=new myPanel();
f.getContentPane().add(p);
f.setSize(300, 300);
f.setVisible(true);
for(int i=0; i<=50; i++)
{
p.repaint();
x++;
y++;
}
}
class myPanel extends JPanel
{
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(Color.GREEN);
g.fillOval(x, y, 40, 40);
}
}
}
答案 0 :(得分:2)
所以,马上有两件事突然出现在我身上。
repaint
可以合并请求,以减少放置在事件队列/事件调度线程上的工作量。由于循环中没有“人为”延迟,因此RepaintManager
我要做的第一件事是将椭圆位置的管理职责隔离开来,因为在您当前的代码中,它可以从任何地方进行更新,这简直是一团糟
class MyPanel extends JPanel {
private Point posy = new Point(0, 0);
public Point getPosy() {
return posy;
}
public void move() {
Point posy = getPosy();
posy.x++;
posy.y++;
repaint();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.GREEN);
g.fillOval(posy.x, posy.y, 40, 40);
}
}
接下来,我将确保在EDT中修改UI的上下文...
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
Animation a = new Animation();
a.go();
}
});
}
最后,我将利用Swing Timer
来作为动画的伪循环...
public void go() {
f = new JFrame();
MyPanel p = new MyPanel();
f.getContentPane().add(p);
f.setSize(300, 300);
f.setVisible(true);
Timer timer = new Timer(5, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
p.move();
}
});
timer.start();
}
在这种情况下使用Swing Timer
有很多原因。首先,“滴答”是在EDT上执行的,这样可以安全地从内部更新UI,并且在滴答之间“等待”时不会阻塞UI
我建议看看: