6

这是给挥杆专家的。我在这个问题上花费了相当多的时间,所以我要花几行来解释这个问题。

我有一个独立的 java swing 应用程序(java 6)。在我的应用程序中,我有一个带有单选按钮组的框架。我有一个链接到组中所有按钮的操作。该操作检查以查看选择了哪个单选按钮并执行一些工作。“工作”涉及一些背景计算以及在我的应用程序中的其他两个框架中的一些绘画。后台计算是多线程的。

当用户选择其中一个单选按钮时,我想显示一个进度条。However, when a radio button is selected, while the action to the radio button is happening, the progress bar never appears. 我尝试过 jdialog 类型的进度条、玻璃窗格等。在“工作”全部完成之前,它们都不会出现。这似乎是因为 Swing 直到完成相应动作中的“工作”才完成单选按钮的绘制。而且由于 EDT 一次只做一件事,因此永远不会显示进度条对话框(或玻璃窗格)。

然后我尝试使用 SwingWorker 来完成所有这些“工作”。启动进度条(或激活玻璃窗格),启动 SwingWorker 并在 SwingWorker 的 done() 方法中关闭进度条(或停用玻璃窗格)。这似乎可以很好地调出进度条,但是作为“工作”的一部分的绘画有时没有完成,给我留下了一些绘画工件(paintComponent 方法相当复杂,所以这里不想重现)。如果我调整窗口大小,工件就会消失。事实上,如果我使用扩展 Thread 而不是 SwingWorker 的类,就会发生这种情况。这完全是因为 Swing 不是线程安全的,我试图从 EDT 以外的线程执行 GUI 工作。我理解那部分。

我该怎么办?“工作”大约需要 30 秒,如果不向用户显示程序正在运行的某种指示,这似乎太长了。我也尝试将光标更改为等待光标并遇到与上述相同的问题。我唯一能做的就是禁用框架并将框架的标题设置为一些文本,如“工作......”

以前有人见过这个问题吗?

4

2 回答 2

4

我认为您在 SwingWorker 线程中进行工作是正确的,但您不应该尝试在那里进行绘画。

我倾向于:

  • 让 ActionListener show() 进度条,启动 swingworker 然后退出

  • 让工作线程完成工作,并定期在进度条组件上调用 repaint()(这保证是线程安全的)

  • 进度条有它自己的paintComponent(将在EDT 上自动调用)。如有必要,这可以读取一些由工作线程更新的变量以测量进度

  • 当工作线程完成时,让它调用 invokeLater() 在 EDT 上运行最终关闭函数,这将隐藏进度条并执行任何其他与 GUI 相关的清理/向用户显示完成消息等。

于 2010-08-13T00:02:30.780 回答
4

当您将作品从 EDT 转移到摇摆工人(这是正确的做法)时,听起来作品和绘画都转移到了摇摆工人身上。这幅画仍应在 EDT 上进行。您可以通过SwingUtilities.invokeLater从后台线程调用重绘或使用SwingWorker.publish(V...)来实现此目的,这将从您的工作线程获取通知并通过SwingWorker.process( V...)模板方法(您覆盖)。您的process覆盖可以通过重新绘制屏幕的一部分、更新进度或根据需要采取一些其他适当的操作来处理中间通知。在此处完成的任何 UI 更改都将可见,而无需等待其余工作完成。

于 2010-08-12T23:46:25.540 回答