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
已经尝试了一段时间,进展不快。当我单击我的播放按钮(触发 ActionEvent)时,我希望在 JFrame 中具有 update/toggle 生存能力的元素。然而,这些似乎只在 actionPerformed 方法完成后更新。这是我认为正在发生的事情,因为我的 SoundPlayer 对象的构造函数触发了 (Thread.sleep)s,导致明显的延迟。我确实读过
如下所示,我尝试重新绘制 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