用于在工作线程中阻止Java Swing用户的模式

时间:2011-03-24 11:59:11

标签: java swing concurrency

正如大多数Java程序员所知,Swing GUI的更新只应在AWT事件派发线程上完成,建议在“worker”线程上执行长时间运行的进程,并使用事件调度线程将更新发送到事件调度线程SwingUtilities.invokeAndWait()SwingUtilities.invokeLater()

在长时间运行的过程完成后,如何阻止用户继续使用该应用程序?你是否使控件变灰,然后让工作线程使用上面提到的SwingUtilities调用重新启用它们?

是否有更好的替代模式?

3 个答案:

答案 0 :(得分:3)

我会考虑3个解决方案:

  • 禁用面板的组件:这通常就是我的工作。不幸的是,Swing没有提供一种简单的方法来禁用面板及其所有子节点,但是很容易进行递归(请参阅this other SO answer)。另一个问题是,启用和禁用某些Swing组件时看起来相同(例如,JList)
  • 使用CardLayout隐藏面板:在包含CardLayout的面板中,添加2个组件。第一个是托管要停用的组件的面板,第二个是显示“加载”或“请稍候”消息的面板。 JLabel中的简单Gridbaglayout可以解决问题。然后,你只需要从一个切换到另一个。我将这种技术用于显示计算/请求结果的地方。
  • 在面板上放置一些消耗鼠标事件的组件:您可以使用LayeredPane自行完成,也可以使用专用实用程序。 JXLayer可以做到这一点(我读到JXLayer将包含在Java 7中,因此这可能成为解决此类问题的'标准')。

答案 1 :(得分:2)

有几种方法和选择,主要取决于GUI的设计和布局。

  • 使用进度条 - 替换您不希望用户触摸进度条的面板或区域。这样可以防止您不得不处理您不想要的事件,同时仍然向用户说明后台发生的事情。
  • 禁用按钮并添加等待光标 - 在工作完成时使用setEnable(false)并且可能将光标更改为等待光标。这再次表明,只有暂时的选项才可用。
  • 不响应事件或抛出GlassPane - 这不是用户友好,因为它使应用程序看起来没有响应,但在某些情况下它是可以接受的。

答案 2 :(得分:0)

我看到它完成的一种方法是使用Jframe.setGlassPane()并设置一个吃掉所有事件的组件。你也可以有创意,并在你的玻璃板上使用闪光等旋转等待gif。但请注意,设置玻璃窗格可能不是您想要的。对于更高级的要求,您可能必须使用事件队列。