在继续之前等待Swing完成更新JProgressBar

wch*_*gin 2 java performance swing multithreading

我有JFrame一个CardLayout集作为其布局管理.它有两个JPanel子类.一个是面板,WordsLoadingPanel显示文本"Loading words ..."并且有一个JProgressBar.另一个必须实际加载单词.这需要一段时间(对于100个单词大约10-14秒;这是一个非常有选择性的算法),所以我想向用户保证该程序仍在工作.我在面板中使用加载算法激活属性更改firePropertyChange(String, int, int),并且WordsLoadingPanel正在捕获更改 - 我知道这是因为我为此事件添加了一个侦听器来执行println,并且它可以工作.但是,当我更改println为实际更改JProgressBar的值时,它不会执行任何操作.我知道我正在改变这个值,因为如果我在算法开始之前设置了值,它就可以工作,并且它适用于循环的最后一次迭代.我猜这是因为我的算法正在吃掉计算能力,不会让JProgressBar更新.

所以,我的问题是:如何让我的算法等待Swing(这是AWT调度线程?)在继续之前完成更新进度条?我试过了:

  • Thread.yield 在循环的每次迭代中
  • Thread.sleep(1000L) 在循环的每次迭代中,在try/catch中
  • 将所有内容放入循环中 SwingUtilities.invokeLater(Runnable)
  • 只将CPU密集型算法放入 SwingUtilities.invokeLater(Runnable)

编辑:为了进一步支持我的CPU为食算法的假设(听起来像一个孩子的故事...),当我设置JProgressBar不确定的,它只是开始移动的算法结束.

有没有人有什么建议?

谢谢!

Mat*_*ira 5

要在后台执行昂贵的操作,请考虑使用SwingWorker该类.该文档包含有关如何使用它来执行与单独线程中的用户界面交互的任务的示例,包括JProgressBars中的进度显示.

如果您无法理解课程的工作原理,请考虑:

  • SwingWorker是一个泛型类,它带有两个参数:TV
  • doInBackground方法返回T并在单独的线程中执行.
  • 由于Swing只能在Event Dispatch Thread中进行操作,因此您可能无法操作Swing doInBackground.
  • process方法将a List<V>作为参数,并在Event Dispatch Thread上异步调用.
  • publish方法接受V...参数并将它们发送给process方法中的处理.

结论:

  • T 是计算结果的类型,如果有的话.
  • V 是操作用户界面所需的数据类型.
  • 你的算法应该完全运行doInBackground.
  • 应该在process方法中操纵用户界面.
  • 您的算法应该用于publish将数据发送到process方法.

  • @WChargin:如果你想使用进程/发布方法,那么SwingWorker的第二个泛型参数不应该是Void,而应该是进程传递给publish的对象类型.如果您需要更具体的帮助,请发布[SSCCE](http://sscce.org),我们可以帮助您修改它以向您展示您可以尝试的内容. (2认同)