我有两个几乎相同的类:AnimationFrame1 和 AnimationFrame2。这两个类都显示一个蓝色球在 500 x 500 窗口中水平来回移动。除了 runAnimation() 和 createAndShowGUI() 方法之外,这两个类是相同的。在其 runAnimation() 方法中,AnimationFrame1 使用 while 循环和 sleep 方法来创建动画循环,而 AnimationFrame2 使用 Swing Timer。在其 createAndShowGUI() 方法中,AnimationFrame1 创建了一个新线程并在其上调用 runAnimation() 方法,而 AnimationFrame2 仅调用 runAnimation() 方法而没有新线程。
编译完这两个类后,我发现使用 Swing Timer 的 AnimationFrame2 显示的动画更流畅,不像 AnimationFrame1 中显示的动画那样卡顿,后者使用 while 循环和 sleep 方法。我的问题是:为什么 AnimationFrame1 的动画显示比 AnimationFrame2 更卡顿?我已经四处寻找了这个原因,但到目前为止还没有找到任何东西。
另外,我显然是 Java 新手,所以如果您发现我的代码有任何问题或者您知道我可以改进它的任何方法,请告诉我。
这是AnimationFrame1:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
class AnimationFrame1 extends JPanel {
int ovalX;
int prevX;
Timer timer;
boolean moveRight;
BufferedImage img;
public AnimationFrame1() {
setPreferredSize(new Dimension(500, 500));
}
public void runAnimation() {
moveRight = true;
img = null;
ovalX = 0;
prevX = 0;
while(true) {
if (moveRight == true) {
prevX = ovalX;
ovalX = ovalX + 4;
}
else {
prevX = ovalX - 4;
ovalX = ovalX - 4;
}
repaint();
if (ovalX > 430) {
moveRight = false;
}
if (ovalX == 0) {
moveRight = true;
}
try {
Thread.sleep(25);
}
catch(Exception e) {
}
}
}
public void paintComponent(Graphics g) {
if (img == null) {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice gs = ge.getDefaultScreenDevice();
GraphicsConfiguration gc = getGraphicsConfiguration();
img = gc.createCompatibleImage(78, 70);
Graphics gImg = img.getGraphics();
gImg.setColor(getBackground());
gImg.fillRect(0, 0, getWidth(), getHeight());
gImg.setColor(Color.BLUE);
gImg.fillOval(4, 0, 70, 70);
gImg.dispose();
}
g.drawImage(img, ovalX, 250, null);
}
public static void createAndShowGUI() {
JFrame mainFrame = new JFrame();
final AnimationFrame1 animFrame = new AnimationFrame1();
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.add(animFrame);
mainFrame.pack();
mainFrame.createBufferStrategy(2);
mainFrame.setVisible(true);
new Thread(new Runnable() {
public void run() {
animFrame.runAnimation();
}
}).start();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
这是AnimationFrame2:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
class AnimationFrame2 extends JPanel {
int ovalX;
int prevX;
Timer timer;
boolean moveRight;
BufferedImage img;
public AnimationFrame2() {
setPreferredSize(new Dimension(500, 500));
}
public void runAnimation() {
moveRight = true;
img = null;
ovalX = 0;
prevX = 0;
timer = new Timer(25, new ActionListener() {
public void actionPerformed(ActionEvent ae) {
if (moveRight == true) {
prevX = ovalX;
ovalX = ovalX + 4;
}
else {
prevX = ovalX - 4;
ovalX = ovalX - 4;
}
repaint();
if (ovalX > 430) {
moveRight = false;
}
if (ovalX == 0) {
moveRight = true;
}
}
});
timer.start();
}
public void paintComponent(Graphics g) {
if (img == null) {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice gs = ge.getDefaultScreenDevice();
GraphicsConfiguration gc = getGraphicsConfiguration();
img = gc.createCompatibleImage(78, 70);
Graphics gImg = img.getGraphics();
gImg.setColor(getBackground());
gImg.fillRect(0, 0, getWidth(), getHeight());
gImg.setColor(Color.BLUE);
gImg.fillOval(4, 0, 70, 70);
gImg.dispose();
}
g.drawImage(img, ovalX, 250, null);
}
public static void createAndShowGUI() {
JFrame mainFrame = new JFrame();
final AnimationFrame2 animFrame = new AnimationFrame2();
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.add(animFrame);
mainFrame.pack();
mainFrame.createBufferStrategy(2);
mainFrame.setVisible(true);
animFrame.runAnimation();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}