【问题标题】:How to properly implement a glass pane in Java?如何在 Java 中正确实现玻璃窗格?
【发布时间】:2015-01-23 22:17:11
【问题描述】:

我正在尝试为我的大型 Swing 程序添加一个花哨的 InfiniteProgressPanel 作为 GlassPane。但是,它没有出现。它看起来像这样:

...
InfiniteProgressPanel glassPane = new InfiniteProgressPanel();
setGlassPane(glassPane);
...
glassPane.start();
doSomeStuff();
glassPane.stop();
...

我相信它与它要掩盖的长进程在同一个线程中运行。我承认,我对线程的了解还不够,我可能应该弄清楚如何在单独的线程中运行 InfiniteProgressPanel GlassPane,以及在它自己的线程中运行长进程。

【问题讨论】:

  • 你在玻璃板上打过setVisible(true)吗?
  • ...设置为框架 GlassPane 后

标签: java multithreading swing progress glasspane


【解决方案1】:

请务必:

  • 在后台线程中运行所有长时间运行的代码。这是必须的。

    听起来不错!我该怎么做?将所有长时间运行的代码封装在 .invokeLater 方法中?那应该是 SwingUtilities.invokeLater 还是 EventQueue.invokeLater?到底有什么区别?

    • 不,通过使用SwingUtilities.invokeLater(new MyRunnable),您所做的恰恰相反——您保证长时间运行的代码将在Swing 事件线程上调用——与你想要什么。而是使用 SwingWorker 的 doInBackground() 方法来运行长时间运行的代码。关于您的第二点,SwingUtilities.invokeLaterEventQueue.invokeLater 之间没有任何区别。
  • 在 Swing 事件线程上进行大多数 Swing 调用,这也是必须

    太棒了!再说一次,我该怎么做?和上面一样吗?

    • 如上所述,通过使用 SwingUtilities.invokeLater(new MyRunnable),或者如果您使用的是 SwingWorker,则使用其发布/处理方法对,因为 SwingWorker 教程将向您展示。
  • 在您的玻璃窗格上调用 setVisible(true),因为根据 JRootPane API,默认情况下所有玻璃窗格都是不可见的。

    Romain Guy 的 InfiniteProgressPanel 似乎不需要 setVisible(true)。在调用 InfiniteProgressPanel.start() 方法时出现。

    • 这个我不熟悉,有链接吗?

【讨论】:

  • 对每一点: 1) 听起来很棒!我该怎么做?将所有长时间运行的代码封装在 .invokeLater 方法中?那应该是SwingUtilities.invokeLater 还是EventQueue.invokeLater?无论如何,有什么区别? 2)太棒了!再说一次,我该怎么做?和上面一样吗? 3) Romain Guy 的 InfiniteProgressPanel 似乎不需要setVisible(true)。在调用InfiniteProgressPanel.start() 方法时出现。
  • 太棒了!感谢您对我的问题的简洁回答。关于 Romain Guy 的 InfiniteProgressPanel,请参阅该链接。他还有一篇文章(我认为是关于 codeidol),其中详细介绍了 IPP,但我现在找不到。 codeidol.com 目前已关闭。同时,我将开始对 SwingWorker 以及如何在我丑陋的程序中正确使用它进行更多研究。再次感谢!
  • 好的,我已经对我的 GUI 进行了 .invokeLater 方法调用,所以已经处理好了。我在长时间运行的进程中忽略了 SwingWorker 类。我现在把它们都准备好了。 glassPane.start();worker.execute(); 之前被调用,而.done()SwingWorker 方法包括glassPane.stop();。测试一下,一切似乎都奏效了!耶!非常感谢大家!
【解决方案2】:

线程本质上是同一程序中的不同进程。

在java中,有很多不同的线程类型,你需要的就是SwingWorker

Oracle 文档中对此的定义/用法是:

当一个 Swing 程序需要执行一个长时间运行的任务时,它通常使用一个工作线程,也称为后台线程。在工作线程上运行的每个任务都由 javax.swing.SwingWorker 的一个实例表示。 SwingWorker 本身是一个抽象类;您必须定义一个子类才能创建 SwingWorker 对象;匿名内部类对于创建非常简单的 SwingWorker 对象通常很有用。

如您所见,这就是您所需要的;一个背景线程。


final InfiniteProgressPanel glassPane;

...

class GlassPaneHandler extends SwingWorker<String, Object> {
    @Override
   public String doInBackground() {
       glassPane.start();
       return setUpPaneAndStuff();
   }

    @Override
   protected void done() {
       try {
           glassPane.stop();
       } catch (Exception e) {  } //ignore
   }

   private void setUpPaneAndStuff() {
       //code
   }
}

...

(new GlassPaneHandler()).execute(); //place this in your code where you want to initiate the pane

更多见:http://docs.oracle.com/javase/8/docs/api/javax/swing/SwingWorker.html

【讨论】:

  • 这将假定 glassPane.start 无论如何都不会与 UI 交互...
【解决方案3】:

当您更新 Swing UI 时,您需要在 Swing 的事件线程中进行。这包括创建组件或任何类型的进度更新。您可以通过SwingUtilities.invokeLater(Runnable) 方法执行此操作。

因此,如果在后台线程中,您应该创建玻璃窗格并通过 invokeLater 显示它。从长期运行的进程线程对玻璃窗格的任何进度更新都应通过 invokeLater 完成。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-18
    • 2012-02-23
    • 1970-01-01
    • 2010-10-06
    相关资源
    最近更新 更多