等待Swing完成更新JProgressBar,然后继续 [英] Wait for Swing to finish updating JProgressBar before continuing
问题描述
我有一个JFrame
,它的布局管理器设置为CardLayout
.其中有两个JPanel
子类.一个是面板WordsLoadingPanel
,其中显示文本正在加载单词..."并具有JProgressBar
.另一个必须实际加载单词.这需要一段时间(100个单词大约需要10-14秒;这是一个非常有选择性的算法),因此我想向用户保证程序仍在运行.我使面板中的加载算法使用firePropertyChange(String, int, int)
触发属性更改,并且WordsLoadingPanel
可以很好地捕获更改-我知道这是因为我为此事件添加了一个侦听器以执行println
,并且它可以正常工作.但是,当我将println
更改为实际更改JProgressBar
的值时,它什么也没做.我知道我正在正确更改值,因为如果我在算法开始之前设置值,则和会在循环的最后一次迭代中起作用.我猜这是因为我的算法正在消耗计算能力,并且不允许JProgressBar
更新.
I have a JFrame
with a CardLayout
set as its layout manager. This has two JPanel
subclasses in it. One is a panel, WordsLoadingPanel
, which displays the text "Loading words..." and has a JProgressBar
. The other has to actually load the words. This takes a while (about 10-14 seconds for 100 words; it's a pretty selective algorithm), so I want to assure the user that the program is still working. I made the loading algorithm in the panel fire a property change with firePropertyChange(String, int, int)
, and the WordsLoadingPanel
is catching the change just fine - I know this because I added a listener for this event to perform a println
, and it works. However, when I change the println
to actually changing the JProgressBar
's value, it doesn't do anything. I know I'm changing the value right, because if I set the value before the algorithm starts, it works, and it works on the last iteration of the loop. I'm guessing this is because my algorithm is eating the computing power and won't let JProgressBar
update.
所以,我的问题是:如何让我的算法等待Swing(这将是AWT Dispatching Thread?)在继续之前完成更新进度条吗?我尝试过:
So, my question is: How do I make my algorithm wait for Swing (would this be the AWT Dispatching Thread?) to finish updating the progress bar before continuing? I've tried:
-
在循环的每次迭代中
-
Thread.yield
-
Thread.sleep(1000L)
在循环的每次迭代中,尝试/捕获 - 将所有内容放入
SwingUtilities.invokeLater(Runnable)
的循环中
- 仅在
SwingUtilities.invokeLater(Runnable)
中放入CPU密集型算法
Thread.yield
in each iteration of the loopThread.sleep(1000L)
in each iteration of the loop, in a try/catch- putting everything in the loop in a
SwingUtilities.invokeLater(Runnable)
- putting only the CPU-intensive algorithm in a
SwingUtilities.invokeLater(Runnable)
为进一步支持我的CPU进食算法假设(听起来像儿童故事……),当我将JProgressBar
设置为不确定时,它只会在算法完成后开始移动
To further support my hypothesis of the CPU-eating algorithm (sounds like a children's story…), when I set the JProgressBar
to indeterminate, it only starts moving after the algorithm finishes.
有人有什么建议吗?
谢谢!
推荐答案
To do expensive operations in background, consider using the SwingWorker
class. The documentation has examples on how to use it to do tasks that interact with the user interface in a separate thread, including progress display in JProgressBar
s.
如果您在理解类的工作方式时遇到困难,请考虑:
If you have trouble understanding how the class works, consider:
-
SwingWorker
是具有两个参数的通用类:T
和V
-
doInBackground
方法返回T
,并在单独的线程中执行. - 由于只能在事件分发线程中操纵Swing,因此您不能在
doInBackground
中操纵Swing. -
process
方法将List<V>
作为参数,并在事件调度线程上被异步调用. -
publish
方法采用V...
参数,并将其发送给process
方法进行处理.
SwingWorker
is a generic class that takes two parameters:T
, andV
- The
doInBackground
method returnsT
and is executed in a separate thread. - Since Swing may only be manipulated in the Event Dispatch Thread, you may not manipulate Swing in
doInBackground
. - The
process
method takes aList<V>
as a parameter and is called asynchronously on the Event Dispatch Thread. - The
publish
method takesV...
arguments and sends them for processing in theprocess
method.
结论:
-
T
是计算结果的类型(如果有). -
V
是操作用户界面所需的数据类型. - 您的算法应完全在
doInBackground
中运行. - 用户界面应在
process
方法中进行操作. - 您的算法应使用
publish
将数据发送到process
方法.
T
is the type of the result of the computation, if any.V
is the type of the data needed to manipulate the user interface.- Your algorithm should run entirely in
doInBackground
. - The user interface should be manipulated in the
process
method. - Your algorithm should use
publish
to send data to theprocess
method.
这篇关于等待Swing完成更新JProgressBar,然后继续的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!