Swing中的任何动画都需要考虑Event Dispatching Thread。
您应该永远不要在可能阻止它的EDT内容中执行任何操作(例如循环或I/O),因为这会阻止EDT(除其他之外)处理绘制请求。
你总是应该使用能够支持双缓冲的表面,如JPanel
,因为这将有助于消除闪烁
下面以javax.swing.Timer
两幅图像之间进行切换...
public class TestPacMan {
public static void main(String[] args) {
new TestPacMan();
}
public TestPacMan() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new PacManPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class PacManPane extends JPanel {
private BufferedImage pacOpened;
private BufferedImage pacClosed;
private BufferedImage frame;
private boolean opened = true;
public PacManPane() {
try {
pacOpened = ImageIO.read(new File("PC-Closed.png"));
pacClosed = ImageIO.read(new File("PC-Opened.png"));
frame = pacOpened;
} catch (IOException exp) {
exp.printStackTrace();
}
Timer timer = new Timer(500, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
opened = !opened;
frame = opened ? pacOpened : pacClosed;
repaint();
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.start();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(500, 500);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
if (frame != null) {
int x = (getWidth() - frame.getWidth())/2;
int y = (getHeight() - frame.getHeight())/2;
g2d.drawImage(frame, x, y, this);
}
g2d.dispose();
}
}
}
这还不够。 *“我尝试了一个for循环”*担心我应该实际上阻止用户界面,但它听起来像你正在使用某个线程... – MadProgrammer
1)为了更好地帮助,请发布[SSCCE](http ://sscce.org/)。 2)但作为一般技巧,构建组件实例时加载图像并将它们存储为类级别属性。 3)如果'G'是一个图形实例,它应该被称为'g'。此外,如果它来自一个组件,它将有一个'ImageObserver' - 所以'g.drawImage(image,x,y,20,20,this);'。 –