Java JFrame:在事件期间(不在计时器内)更新 GUI

Java JFrame: Update GUI during an event (not within a timer)

已经尝试了一段时间,进展不快。当我单击我的播放按钮(触发 ActionEvent)时,我希望在 JFrame 中具有 update/toggle 生存能力的元素。然而,这些似乎只在 actionPerformed 方法完成后更新。这是我认为正在发生的事情,因为我的 SoundPlayer 对象的构造函数触发了 (Thread.sleep)s,导致明显的延迟。我确实读过 使用 Thread.sleep() 会锁定 GUI,但我在 调用 SoundPlayer 之前 进行了更改,所以我认为这不会问题。

如下所示,我尝试重新绘制 JFrame 以及单个元素。尽管我的 println 语句打印了正确的时间,但在 SoundPlayer 的延迟结束之前这些不会更新。

我想到了多线程作为解决方案,但我不明白为什么我需要这样做。感谢您对此事的任何帮助!

public void actionPerformed(ActionEvent e){

    int channel = 0, volume = 0;    //Assigned for safety.
    String musicNotes = "";   //Will be filled with the under-input.
    boolean willPlay = true;    //Assumes will be played.

    /*Stuff that makes 'willPlay' either true of false*/

    //If nothing is wrong, plays the String!
    if (willPlay) {       //If above parameters are good...
        badNums.setVisible(false);
        prog.setVisible(true);

        if (vis.isSelected())
            prog.setText("Estimated duration: " + estiDuration(musicNotes)*(0.4) + "seconds");
        else
            prog.setText("Duration: " + estiDuration(musicNotes)*(0.3) + "seconds");

        System.out.println("test");
        repaint();
        prog.repaint();

        new SoundPlayer(channel, volume, musicNotes);          //Plays the music!
    } else {
        vis.setVisible(false);
        badNums.setVisible(true);
    }
}

Swing 是单线程的 - 所有用于绘画、事件等的代码...都在此线程(称为 EDT)上运行。如果你有一个很长的 运行 任务并将它放在 EDT 上,它在完成之前不能做任何其他事情(注意调用 repaint 不会直接 ​​repaint Component, 所以 运行 在此调用之后很长的东西并不意味着 Component 实际上会在之前绘制自己)。如果您需要执行冗长的操作,请在不同的 Thread 中执行 - 这可以直接使用 Thread, or using a SwingWorker 来完成。如果是前者,请确保使用 SwingUtilities.invokeXXX

将对 Swing 的任何调用分派到 EDT