这是针对那里的摇摆专家。我花了相当多的时间来解决这个问题,所以我需要几行来解释这个问题。
我有一个独立的java swing应用程序(java 6)。在我的应用程序中,我有一个带有单选按钮组的框架。我有一个链接到组中所有按钮的操作。该操作检查以查看选择了哪个单选按钮并执行某些操作。 “工作”涉及一些背景计算以及我的应用程序中的两个其他框架中的一些绘画。后台计算是多线程的。
当用户选择其中一个单选按钮时,我想显示一个进度条。 但是,当选择单选按钮时,在发生对单选按钮的操作时,进度条永远不会出现。我尝试了jdialog类型的进度条,玻璃窗格等。在“工作”全部完成之前,它们都没有出现。这似乎是因为Swing没有完成对单选按钮的绘制,直到相应动作中的“工作”完成。由于EDT一次只做一件事,因此从不显示进度条对话框(或玻璃窗格)。
然后我尝试使用SwingWorker来完成所有这些“工作”。启动进度条(或激活玻璃窗格),启动SwingWorker并关闭SwingWorker的done()方法中的进度条(或停用玻璃窗格)。这似乎提升了进度条很好,但是作为“工作”一部分的绘画有时候没有完成,留下了一些绘画工件(paintComponent方法非常复杂,所以不想在这里重现)。如果我调整窗口大小,工件就会消失。事实上,如果我使用扩展Thread而不是SwingWorker的类,就会发生这种情况。这都是因为Swing不是线程安全的,我试图从除EDT之外的线程进行GUI工作。我理解那部分。
我该怎么办? “工作”大约需要30秒,如果没有向用户显示程序正在运行的某种迹象,那么这似乎太长了。我也尝试将光标更改为等待光标并遇到与上述相同的问题。我唯一能做的就是禁用框架并将框架的标题设置为某些文本,例如“工作......”
之前有人见过这个问题吗?
答案 0 :(得分:4)
当你将作品从EDT移动到摇摆工作者(这是正确的事情)时,听起来工作和绘画都转移到摇摆工作者身上。这幅画应该仍然在美国东部时间发生。您可以使用SwingUtilities.invokeLater
从后台线程调用重绘,或使用SwingWorker.publish(V...)来实现此目的,该SwingWorker.process(V...)将从您的工作线程接收通知,并通过{{3在EDT上提供它们模板方法(你重写)。您的process
覆盖可以通过重新绘制部分屏幕,更新进度或根据需要采取其他适当的操作来处理中间通知。在此处完成的任何UI更改都将可见,而无需等待其余工作完成。
答案 1 :(得分:4)
我认为你在SwingWorker线程中完成这项工作是正确的,但你不应该尝试在那里进行绘画。
我倾向于:
让ActionListener show()显示进度条,设置swingworker然后退出
让工作线程完成工作,并定期调用进度条组件上的repaint()(这保证是线程安全的)
进度条有自己的paintComponent(将在EDT上自动调用)。如有必要,可以读取工作线程更新的一些变量,以衡量进度
当工作线程完成时,让它调用invokeLater()在EDT上运行最终关闭功能,这将隐藏进度条并执行任何其他与GUI相关的清理/显示完成消息给用户等。