Thread.sleep(1000);
将阻止当前运行的线程
paintComponent
从Event Dispatching Thread的上下文中调用.
在完成处理当前(在本例中为"paint")事件之前,Swing不会更新UI的状态,这意味着当它被阻止时Thread.sleep
,UI上不会更新任何内容,也不会处理任何新事件.
Swing是一个单线程框架.您永远不应该在Event Dispatching Thread的上下文中执行任何阻塞或长时间运行的操作.
查看Swing中的Concurrency以获取更多详细信息以及如何使用Swing Timers获得可能的解决方案.
作为旁注,如果UI或任何UI依赖于任何paint方法中的变量,则不应修改状态.绘画应该只绘制组件的当前状态,永远不要修改它,这包括repaint
直接或间接调用
例如...
import java.awt.Color; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.Graphics; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.Timer; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; public class GameRunner extends JPanel { private int xPos = 300; @Override protected void paintComponent(Graphics g) { super.paintComponent(g); g.setColor(Color.blue); g.fillRect(xPos, 400, 100, 100); repaint(); } public GameRunner() { Timer timer = new Timer(1000, new ActionListener() { private boolean state = false; @Override public void actionPerformed(ActionEvent e) { if (state) { xPos = 300; } else { xPos = 600; } state = !state; repaint(); } }); timer.start(); } @Override public Dimension getPreferredSize() { return new Dimension(700, 500); } public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { ex.printStackTrace(); } JFrame frame = new JFrame("Testing"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(new GameRunner()); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } }