Java游戏开发:如何实现JButton点击后JTextField依次显示骰子值?
问题分析与解决方案
嘿,这个问题我太熟悉了!你碰到的核心问题是Swing的事件调度线程(EDT)被阻塞了:
当你点击按钮时,jButton2ActionPerformed方法是在EDT里执行的——这个线程负责处理所有UI事件和UI更新操作。你调用Thread.sleep(2000)会让EDT暂停2秒,这期间整个UI都会卡住,而且所有的UI更新(dice.setText(...)和dicecom.setText(...))都会被延迟到sleep结束后才一起执行,所以看起来两个随机值是同时显示的。
解决方案1:使用Swing Timer(推荐)
Swing提供了javax.swing.Timer,专门用于处理延迟的UI任务,它不会阻塞EDT,是这种简单延迟场景的最佳选择:
import javax.swing.Timer; import java.util.Random; private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) { Random rand = new Random(); // 立刻更新第一个骰子的值 int a = rand.nextInt(6) + 1; dice.setText(String.valueOf(a)); // 创建一个延迟2秒的Timer,执行第二个骰子的更新 Timer delayTimer = new Timer(2000, e -> { int b = rand.nextInt(6) + 1; dicecom.setText(String.valueOf(b)); // 执行完毕后停止Timer,避免重复触发 ((Timer) e.getSource()).stop(); }); delayTimer.setRepeats(false); // 设置为只执行一次 delayTimer.start(); }
为什么这个可行?
- Timer会在后台调度任务,2秒后在EDT里执行更新操作,不会阻塞当前的事件处理流程。
- 第一个骰子的UI更新会立刻生效,2秒后第二个骰子的值才会显示,完全符合你的需求。
解决方案2:使用SwingWorker(适合复杂后台任务)
如果之后你需要在延迟期间执行一些后台计算,可以用SwingWorker,它能在后台线程处理耗时操作,然后回到EDT更新UI:
import javax.swing.SwingWorker; import java.util.Random; private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) { Random rand = new Random(); int a = rand.nextInt(6) + 1; dice.setText(String.valueOf(a)); new SwingWorker<Void, Void>() { @Override protected Void doInBackground() throws InterruptedException { // 在后台线程执行sleep,不会阻塞EDT Thread.sleep(2000); return null; } @Override protected void done() { // 回到EDT更新第二个骰子的值 int b = rand.nextInt(6) + 1; dicecom.setText(String.valueOf(b)); } }.execute(); }
关键注意事项
- 永远不要在EDT里执行耗时操作(比如
Thread.sleep()、网络请求、复杂计算),否则UI会失去响应。 - 所有的UI组件更新操作必须在EDT里执行,Timer和SwingWorker都帮你处理了这一点,不用手动切换线程。
内容的提问来源于stack exchange,提问作者Ritesh Narayan Das
相关产品推荐
相关产品推荐

