1

我正在尝试在 Java 中创建一个简单的动画,该动画显示一个蓝色球在 500 x 500 窗口中水平移动。球应该以 1px/30ms 的速率移动。问题是,仅在 while 循环退出时才绘制窗口,而不是在我想要的 while 循环的每次迭代期间绘制窗口。这导致蓝色球被涂在其最终位置。你能告诉我我在这里做错了什么吗?我还尝试使用 paintComponent() 方法在 EDT 上执行此代码并得到相同的结果。此外,正如其他帖子所建议的那样,我在使用 EDT 和 paintComponent() 方法时使用 paintImmediately(0, 0, getWidth(), getHeight()) 而不是 repaint() 得到了相同的结果。我正在尝试在不使用计时器的情况下完成所有这些工作。

import javax.swing.*;
import java.awt.*;

class AnimationFrame extends JPanel {

    int ovalX = 50;
    long animDuration = 5000;
    long currentTime = System.nanoTime() / 1000000;
    long startTime = currentTime;
    long elapsedTime = currentTime - startTime;

    public AnimationFrame() {
        setPreferredSize(new Dimension(500, 500));
        runAnimation();
    }

    public void runAnimation() {
        while (elapsedTime < animDuration) {
            currentTime = System.nanoTime() / 1000000;
            elapsedTime = currentTime - startTime;
            System.out.println(elapsedTime);
            ovalX = ovalX + 1;
            try {
                Thread.sleep(30);
            }
            catch (Exception e) {
            }
            repaint();
        }
    }

    public void paint(Graphics g) {
        Rectangle clip = g.getClipBounds();
        g.setColor(Color.BLACK);
        g.fillRect(clip.x, clip.y, clip.width, clip.height);
        g.setColor(Color.BLUE);
        g.fillOval(ovalX, 250, 70, 70);
    }

    public static void main(String[] args) {
        createAndShowGUI();
    }

    public static void createAndShowGUI() {
        JFrame mainFrame = new JFrame();
        mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        mainFrame.add(new AnimationFrame());
        mainFrame.pack();
        mainFrame.setVisible(true);
    }
}
4

2 回答 2

4

我查看了您的代码并注意到您正在调用从“AnimationFrame”的构造函数中运行动画的方法,该构造函数正在添加到“mainFrame”中。

这样做的问题是您试图在对象完成构建之前制作动画,必须在将其添加到 mainFrame 之前完成动画,而 mainFrame 尚未使其在屏幕上可见。

我对您的代码进行了以下更改,现在我看到一个蓝色的球在框架上移动。

import javax.swing.*;
import java.awt.*;

class AnimationFrame extends JPanel {

    int ovalX = 50;
    long animDuration = 5000;
    long currentTime = System.nanoTime() / 1000000;
    long startTime = currentTime;
    long elapsedTime = currentTime - startTime;

    public AnimationFrame() {
        setPreferredSize(new Dimension(500, 500));
        //i removed the call to runAnimation from here

    }

    public void runAnimation() {
        while (elapsedTime < animDuration) {
            currentTime = System.nanoTime() / 1000000;
            elapsedTime = currentTime - startTime;
            System.out.println(elapsedTime);
            ovalX = ovalX + 1;
            try {
                Thread.sleep(30);
            }
            catch (Exception e) {
            }
            repaint();
        }
    }

    @Override
    public void paint(Graphics g) {
        Rectangle clip = g.getClipBounds();
        g.setColor(Color.BLACK);
        g.fillRect(clip.x, clip.y, clip.width, clip.height);
        g.setColor(Color.BLUE);
        g.fillOval(ovalX, 250, 70, 70);
    }

    public static void main(String[] args) {
        createAndShowGUI();
    }

    public static void createAndShowGUI() {
        JFrame mainFrame = new JFrame();
        mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        AnimationFrame animationPanel = new AnimationFrame();
        mainFrame.add(animationPanel);
        mainFrame.pack();
        mainFrame.setVisible(true);
        //I made the call to runAnimation here now
        //after the containing frame is visible.
        animationPanel.runAnimation();
    }
}
于 2013-01-15T18:53:47.650 回答
1

您需要在单独的线程中执行循环。请参阅本教程- http://101.lv/learn/Java/ch10.htm

于 2013-01-15T18:36:26.523 回答