使用 while 循环和延迟更新 Swing GUI

Updating Swing GUI with while loop and delay

我有一个应该更新程序数据和 GUI 的 while 循环,但是 GUI 部分冻结,直到 while 循环执行完毕。

这是我的代码:

while(game.getCompTotal() < 17) {
    try {
        Thread.sleep(2500);
    } catch (Exception ex){
        ex.printStackTrace();
    }
    game.compHit();           // Program data update

    updateCardPanels();       // GUI update -- Does not update until the while loop finishes.

    if(game.checkCompBust()){
        if(JOptionPane.showConfirmDialog(this, "Dealer Busted.  Play again?") == JOptionPane.YES_OPTION){
            init();           // Reset
        }   
    }
}

我尝试过使用 SwingUtilities.invokeLater()Swing Timer,但我并不真正了解 SwingUtilities.invokeLater() 的工作原理或如何在 EDT 上使用 Swing Timer。我的问题是如何在 while 循环中更新 GUI 和程序数据?

这是我尝试的 invokeLater() 代码:

SwingUtilities.invokeLater(new Runnable() {
    public void run() {
        Timer t = new Timer(100, new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e) {
                updateCardPanels();
            }
        });
        t.setInitialDelay(0);
        t.start();
    }
});
  1. 看起来你的 while 循环在 EDT 上,这就是它在执行时冻结 GUI 的原因。 切勿在美国东部时间调用 Thread.sleep

  2. 所有 SwingUtilities.invokeLater 所做的就是将 Runnable 放入队列中,以便 EDT 在某个时间点 运行 它。 SwingUtilities.invokeLater 应该是来自非 EDT 线程的 运行。不需要使用 SwingUtilities.invokeLater 启动 Swing Timer。您可以直接从 EDT 启动它。

  3. Swing 计时器使用一个单独的线程,运行s 并在 EDT 线程上定期调用指定的 ActionListener

您可以将 while 循环替换为摆动计时器(假设间隔为 1 秒)并检查其 actionPerformed 调用中的 game.getCompTotal() < 17 条件。