我有一个JFrame
,其CardLayout
设置为其布局管理器。这里有两个JPanel
子类。一个是面板WordsLoadingPanel
,它显示文本“正在加载单词...”并且有一个JProgressBar
。另一个必须实际加载单词。这需要一段时间(对于100个单词大约10-14秒;这是一个非常有选择性的算法),所以我想向用户保证该程序仍在工作。我在面板中使用加载算法激活了firePropertyChange(String, int, int)
的属性更改,并且WordsLoadingPanel
正在捕获更改 - 我知道这是因为我为此事件添加了一个侦听器来执行{{1它有效。但是,当我将println
更改为实际更改println
的值时,它不会执行任何操作。我知道我正在改变正确的值,因为如果我在算法开始之前设置了值,它就可以工作,和它可以在循环的最后一次迭代中工作。我猜这是因为我的算法正在消耗计算能力,不会让JProgressBar
更新。
所以,我的问题是:如何让我的算法等待Swing(这是AWT调度线程?)在继续之前完成更新进度条?我试过了:
JProgressBar
Thread.yield
,在try / catch Thread.sleep(1000L)
SwingUtilities.invokeLater(Runnable)
编辑:为了进一步支持我关于CPU吃饭算法的假设(听起来像孩子的故事......),当我将SwingUtilities.invokeLater(Runnable)
设置为不确定时,它只会在之后开始移动算法完成。
有人有任何建议吗?
谢谢!
答案 0 :(得分:5)
要在后台执行昂贵的操作,请考虑使用SwingWorker
类。该文档包含有关如何使用它来执行与单独线程中的用户界面交互的任务的示例,包括JProgressBar
中的进度显示。
如果您无法理解课程的运作方式,请考虑:
SwingWorker
是一个通用类,它带有两个参数:T
和V
doInBackground
方法返回T
并在单独的线程中执行。doInBackground
中操纵Swing。process
方法将List<V>
作为参数,并在事件调度线程上异步调用。publish
方法接受V...
个参数并将其发送给process
方法进行处理。总结:
T
是计算结果的类型,如果有的话。V
是操作用户界面所需的数据类型。doInBackground
。process
方法操作用户界面。publish
将数据发送到process
方法。答案 1 :(得分:2)
new Thread(Runnable).start
)。所以,我的代码现在是
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new Thread(new Runnable () {
public void run () {
window.keyboardTrainingPanel.initialize();
}
}).start();
}
});
我希望这可以帮助别人!但是,如果有更好的方法,请随时通知我。