您只需释放一些繁重任务的 EDT 线程并在单独的线程中执行它们。在这种情况下,gif 动画将与其他正在运行的进程一起工作。
您也可以在单独的线程中创建您的应用程序界面(是的,不是在 EDT 内),但仅在您显示它之前。之后您应该在 EDT 内进行所有更改,否则您可能会遇到很多问题。
您也可以稍后在单独的线程中加载更多 UI 元素,只需确保将它们添加到 EDT 内显示的框架/容器中 - 这是最重要的。
这里是一个“重载”界面加载的小例子:
public static void main ( String[] args ) throws InvocationTargetException, InterruptedException
{
// Main window
final JFrame frame = new JFrame ();
final JPanel panel = new JPanel ( new FlowLayout ( FlowLayout.LEFT, 5, 5 ) )
{
public Dimension getPreferredSize ()
{
Dimension ps = super.getPreferredSize ();
ps.width = 0;
return ps;
}
};
frame.add ( new JScrollPane ( panel ) );
frame.setSize ( 600, 500 );
frame.setDefaultCloseOperation ( JFrame.EXIT_ON_CLOSE );
frame.setLocationRelativeTo ( null );
SwingUtilities.invokeAndWait ( new Runnable ()
{
public void run ()
{
frame.setVisible ( true );
}
} );
// Load dialog
final JDialog load = new JDialog ( frame );
JPanel panel2 = new JPanel ( new BorderLayout () );
panel2.setBorder ( BorderFactory.createEmptyBorder ( 15, 15, 15, 15 ) );
load.add ( panel2 );
final JProgressBar progressBar = new JProgressBar ( 0, 100 );
panel2.add ( progressBar );
load.setModal ( false );
load.pack ();
load.setLocationRelativeTo ( frame );
SwingUtilities.invokeAndWait ( new Runnable ()
{
public void run ()
{
load.setVisible ( true );
}
} );
// Heavy task (takes approx. 10 seconds + some time on buttons creation)
for ( int i = 0; i < 100; i++ )
{
Thread.sleep ( 100 );
final JButton button = new JButton ( "Button" + i );
final int finalI = i;
// Updating panel and progress in EDT
SwingUtilities.invokeLater ( new Runnable ()
{
public void run ()
{
panel.add ( button );
button.revalidate ();
progressBar.setValue ( finalI );
}
} );
}
}
如您所见 - 所有界面更新操作都在 EDT 中进行,其他一切都在另一个线程中运行。
还要注意主线程不是 EDT 线程,所以我们可以立即在那里做一些繁重的事情。
在某些情况下,它不需要立即显示加载的界面部分,因此您可以在“繁重”操作结束时将它们一起添加。这将节省一些加载时间,并使初始化代码更加简单。
关于 EDT 的简要说明以及我在回答中所说的话...
...这是我在 Swing L&F 和许多基于 Swing 的应用程序下工作三年后发现的。我挖掘了很多 Swing 的资源,发现了很多鲜为人知的有趣的东西。
如您所知 - 用于界面更新的单线程(其在 Swing 中的 EDT)的整个想法是将每个单独的组件 visual 更新(及其事件)保持在一个队列中,并通过以下方式执行它们那个线程里面的一个。这主要是为了避免绘制问题,因为单个帧内的每个组件都被绘制到保存在内存中的 single 图像上。那里的绘画顺序很严格,因此一个组件不会在最终图像上覆盖另一个组件。绘制顺序取决于通过在另一个容器中添加一些组件或容器而创建的组件树(这是在 Swing 上创建任何应用程序接口时所做的基本操作)。
总而言之 - 您必须将所有视觉更新(可能导致它们的方法/操作)保存在 EDT 中。任何其他可能都可以在 EDT 之外完成 - 例如,您可以在 EDT 之外准备应用程序接口(同样,除非您在已经可见的容器内添加/删除/移动组件)。
在一些非常非常非常罕见的情况下,仍然可能存在一些内部问题。很久以前这里就这个问题进行了很好的讨论:
http://www.velocityreviews.com/forums/t707173-why-does-jdk-1-6-recommend-creating-swing-components-on-the-edt.html
简而言之:自从 JDK 版本 6 以来,Sun 在文档中声明即使是 Swing 组件的创建也应该在 EDT 内完成以避免可能的问题。由于在创建组件时发生的事件,它们可能会出现在某些创建大量接口的特定情况下。
无论如何,我想说的是,在某些情况下,您可能会在 EDT 之外创建您的界面,以避免加载程序/应用程序被卡住。在其他情况下,如果应用程序在界面创建时间卡住并不重要 - 您应该使用 EDT。我不能说更具体的事情,因为一切都取决于你的情况......