.fillOval坐标在repaint()期间不更新

时间:2018-07-18 21:54:59

标签: java swing

我正在阅读一本(过时的)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);
    }
}
}

1 个答案:

答案 0 :(得分:2)

所以,马上有两件事突然出现在我身上。

  1. 更新值的循环可能没有在事件调度线程上运行,这可能导致脏读/写
  2. repaint可以合并请求,以减少放置在事件队列/事件调度线程上的工作量。由于循环中没有“人为”延迟,因此RepaintManager
  3. 可能会将您的所有请求减少为一次更新

我要做的第一件事是将椭圆位置的管理职责隔离开来,因为在您当前的代码中,它可以从任何地方进行更新,这简直是一团糟

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

我建议看看: