无法在Java中获得正常的动画(图形只是出现在另一个地方,不会滑动)



我这里有个问题。下面的程序创建一个动画(从一个点到另一个点的圆)。单击按钮时,动画应开始。

问题是当我单击按钮时,我看不到圆圈在滑动。一段时间后,它只是出现在其他地方。

对我来说(作为初学者)似乎很有趣,如果我不使用按钮,并在 go() 中调用 moveIt() 方法,我会得到一个正常的动画(我可以看到圆在滑动)。

你能给我一些关于这个问题的建议吗?

谢谢。

这是程序:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JButton;
import java.awt.event.*;
final public class MiniMiniMusicPlayer1 implements ActionListener
{
    JFrame frame;
    DrawPanel drawPanel;
    private int X = 7;
    private int Y = 7;

    public static void main(String... args)
    {
        new MiniMiniMusicPlayer1().go();
    }
    private void go()
    {
        frame = new JFrame("Player");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        drawPanel = new DrawPanel();
        frame.getContentPane().add(BorderLayout.CENTER, drawPanel);
        JButton buttonStart = new JButton("Start animation");
        frame.getContentPane().add(BorderLayout.SOUTH, buttonStart);
        buttonStart.addActionListener(this);
        frame.setResizable(false);
        frame.setSize(300, 300);
        frame.setLocationByPlatform(true);
        frame.setVisible(true);

    }
    @Override
    public void actionPerformed(ActionEvent ev){
        moveIt();
    }
    class DrawPanel extends JPanel
    {
        public void paintComponent(Graphics g)
        {
            g.setColor(Color.BLACK);
            g.fillRect(0, 0, this.getWidth(), this.getHeight());
            g.setColor(Color.RED);
            g.fillOval(X, Y, 50, 50);
        }
    }
    private void moveIt()
    {
        for (int i = 0; i < 100; ++i)
        {
            X++;
            Y++;
            try
            {
                Thread.sleep(10);
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
            frame.repaint();
        } 
    }
}

Swing 和 AWT 使用事件调度线程工作。该线程负责处理所有事件(运行事件处理程序,例如按钮的actionPerformed)和重绘请求。

当你从go运行你的moveIt时,它由线程运行。它创建重绘请求,与主线程同时运行的事件调度线程调度这些请求。因此,您可以看到动画。

但是,当您从事件处理程序调用moveIt时,它由事件调度线程本身运行。因此,将执行整个循环,并且所有重绘请求都排队,但线程很忙,并且在完成循环之前无法调度它们。

当它完成循环时,它会调度重绘(或者更确切地说,它只调度一个,不需要重绘 100 次)。重绘是在给定 X 和 Y 的最终状态的情况下完成的。

如果要查看动画,则应确保未在 EDT 中运行它们。例如,您可以为此使用 javax.swing.Timer 对象。

请记住,永远不要在事件处理程序中运行长时间的操作。它阻止了 EDT 并使您的 GUI 无响应。切勿在事件处理程序中使用Thread.sleep()。如果您的长任务应该定期执行某些操作,请使用 Timer 。如果它应该执行一些大任务,例如从数据库加载,请使用 SwingWorker .

最新更新