Java 在程序启动时操作Swing组件的正确方法是什么?
我正在使用NetBeans在Swing中创建一个应用程序。我希望能够在窗口可见后,在其启动期间(仅一次)操作一些组件,例如更新进度条。为此,我有应用程序的主类,称为MainWindow: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
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()调用之间更新进度条的详细信息,请参阅和方法
您可能还需要寻找另一种替代方法来处理对话框等问题。您可以做以下几件事:
JFrame
或JDialog
),您可以附加WindowListener并在WindowOpen方法中进行操作addNotify
方法并在那里执行控制操作HierarchyListener
,并在组件的可显示性发生变化时进行操作始终确保在EDT上执行组件操作。使用
SwingUtilities.invokeLater
进行简单的UI更新,或者使用SwingWorker
进行长时间运行的任务。广告1:我可能没有得到什么东西,但在我看来,我说过要尝试,但没有用。你可以尝试我提供的3种不同方法中的任何一种。在您的情况下,我会使用#2,只需从addNotify调用init(别忘了调用super.addNotify)