Java 在程序启动时操作Swing组件的正确方法是什么?

Java 在程序启动时操作Swing组件的正确方法是什么?,java,swing,multithreading,Java,Swing,Multithreading,我正在使用NetBeans在Swing中创建一个应用程序。我希望能够在窗口可见后,在其启动期间(仅一次)操作一些组件,例如更新进度条。为此,我有应用程序的主类,称为MainWindow: public class MainWindow extends JFrame { public MainWindow() { initComponents(); // NetBeans GUI builder-generated function for setting

我正在使用NetBeans在Swing中创建一个应用程序。我希望能够在窗口可见后,在其启动期间(仅一次)操作一些组件,例如更新进度条。为此,我有应用程序的主类,称为MainWindow:

public class MainWindow extends JFrame
{

public MainWindow()
{
    initComponents(); // NetBeans GUI builder-generated function for setting
                      // up the window components

}

public void Init()
{
     loadLabel.setText("Loading....");
     loadProgressBar.setValue(20);
     doSomething();
     loadProgressBar.setValue(40);
     doSomething();
     loadProgressBar.setValue(80);
     doSomething();
     loadProgressBar.setValue(100);

     loadLabel.setVisible(false);
     loadProgressBar.setVisible(false);
}

/* .... */

public static void main(String args[]) 
{
    java.awt.EventQueue.invokeLater(new Runnable() 
    {
        public void run() 
        {
            mainHandle = new MainWindow();
            mainHandle.setVisible(true);
            mainHandle.Init();
        }
    });
}

}
问题在于,无法观察到Init()函数中用于更新进度条(或操作任何其他GUI组件)的语句的效果。如上图所示,如果从main()内调用Init()函数,窗口将出现,但为空,Init()函数将执行并返回,仅在窗口绘制其内容之后,但Init()所做的任何更改都不可见,因为窗口始终为空且不活动。我还尝试从windowOpened()AWT事件调用init,该事件在窗口完全绘制后执行,但令人惊讶的是,将用于操作组件的任何语句放在那里似乎没有效果,或者说它们被放入队列,并在连续的某个点上快速执行,因此只有最后一个事件的效果(隐藏元素)可以观察到。我设法让它工作的唯一方法是删除整个invokeLater(new Runnable()…)咒语,并将新的MainWindow()、setVisible()、Init()序列直接放在main()中,我猜这非常难看,打破了gui以线程方式运行的概念。正确的方法是什么?当gui准备好被操作时,我应该首先将要执行的代码放在哪里,执行一次语句并将控制返回到主事件循环

我猜目前这是以这样的方式工作的,当Init()函数运行时,gui组件上的任何操作都会被挂起(绘图线程不是独立的,而是在执行操作之前等待Init()完成)。也许我应该让Init()成为一个新线程。。。只有怎样和怎样


谢谢。

您可以将EventQueue.invokeLater()更改为invokeAndWait(),并将对init()的调用移到第二个EventQueue.invokeLater()调用

如果(看起来是这样)doSomething()花费了相当长的时间,那么更好的办法是将Init代码移动到。这可以从MainWindow()构造函数中执行,也可以在main中的setVisible()调用之后执行,这是一种惯用的方式,可以使GUI具有响应性(以防用户厌倦等待并想要退出),并显示一些可见的进展迹象

有关如何在doSomething()调用之间更新进度条的详细信息,请参阅和方法


您可能还需要寻找另一种替代方法来处理对话框等问题。

您可以做以下几件事:

  • 对于windows(如
    JFrame
    JDialog
    ),您可以附加WindowListener并在WindowOpen方法中进行操作
  • 重写
    addNotify
    方法并在那里执行控制操作
  • 附加
    HierarchyListener
    ,并在组件的可显示性发生变化时进行操作

  • 始终确保在EDT上执行组件操作。使用
    SwingUtilities.invokeLater
    进行简单的UI更新,或者使用
    SwingWorker
    进行长时间运行的任务。广告1:我可能没有得到什么东西,但在我看来,我说过要尝试,但没有用。你可以尝试我提供的3种不同方法中的任何一种。在您的情况下,我会使用#2,只需从addNotify调用init(别忘了调用super.addNotify)