在java中显示Gif动画 [英] Displaying Gif animation in java

查看:162
本文介绍了在java中显示Gif动画的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

您好我正在使用Swing在Java 1.6上编写GUI应用程序。

Hello I am writing a GUI application on Java 1.6 with Swing.

我有一个弹出屏幕,当我的Swing gui正在加载时,它应该显示一个gif动画还有一点点。

I have a pop up screen that should display a gif animation while my Swing gui is loading and also a little bit after.

我的弹出屏幕是一个JDialog。动画应显示在以下列方式添加到Jdialog的JLabel上:

My pop up screen is a JDialog. Tthe animation should be displayed on a JLabel that was added to the Jdialog the following way:

ImageIcon myImgIcon = getMyImgIcon();
JLabel imageLbl = new JLabel(myImgIcon);
add(imageLbl, BorderLayout.CENTER); 

现在的事情是动画只在gui加载后显示。我相信在加载GUI时(在我的应用程序中这是一个繁重的操作),EDT非常繁忙,无法运行动画。

Now the thing is that the animation only displays after the gui has been loaded. I believe that while the GUI is loading (which is a heavy operation in my application) the EDT is so busy it can't run the animation.

参见如何使用线程显示动画GIF图像

现在问题是我在不同的线程(不是EDT)上加载GUI是错误的,所以我不知道如何解决问题。

Now the thing is it would be wrong for me to make the GUI load on a different thread (not EDT) so I don't know how to solve the problem.

有没有人有想法?

推荐答案

你只需要释放一些繁重任务的EDT线程,并在一个单独的线程中执行它们。在这种情况下,gif动画将与其他正在运行的进程一起工作。

You just have to free EDT thread of some heavy tasks and do them in a separate thread. In that case gif animation will work together with other processes running.

您也可以在一个单独的线程中创建您的应用程序接口(是的,不在EDT内)但仅直到你显示它。之后你应该在EDT内部进行所有更改,否则你可能会遇到很多问题。

You might also create your application interface in a separate thread (yes yes, not inside the EDT) but only until you display it. Afterwards you have should make all changes inside the EDT, otherwise you might encounter a lot of problems.

您稍后还可以在单​​独的线程中加载更多UI元素,只需确保将它们添加到EDT内显示的框架/容器中 - 这是最重要的事情。

You can also load more UI elements in a separate thread later, just make sure that you add them onto displayed frames/containers inside EDT - that is the most important thing.

以下是类似重型界面加载的一个小例子:

Here is a small example of "heavy-like" interface loading:

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中制作,其他一切都在另一个线程中运行。

As you can see - all the interface update operations are made in EDT, everything else runs inside the other thread.

还要注意主线程不是EDT线程,所以我们可以马上做一些重做。

Also notice that main thread is not EDT thread, so we can do something heavy there right away.

在某些情况下,不需要立即显示界面的加载部分,因此您可以在重操作结束时一起添加它们。这将节省一些加载时间,并使初始化代码更加简单。

In some cases its not needed to display loaded parts of interface right away, so you can add them alltogether at the end of the "heavy" operation. That will save some loading time and will make the initialization code much more simple.

有关EDT的简要说明以及我在答案中所说的内容......

...这是我在Swing L& F和大量基于Swing的应用程序工作三年后找到的东西。我挖掘了很多Swing源代码并发现了很多有趣的东西,这些东西并不为人所知。

...it was something i found after working three years under Swing L&F and lots of Swing-based applications. I digged a lot of Swing sources and found a lot of interesting things that aren't widely known.

如你所知 - 用于接口更新的单线程的整个想法(它在Swing中的EDT)是关于将每个单独的组件可视更新(及其事件)保存在队列中并在该线程内逐个执行它们。这主要是为了避免绘画问题,因为单帧内的每个组件都被绘制到保留在内存中的单个图像。绘画顺序非常严格,因此一个组件不会覆盖最终图像上的另一个组件。绘制顺序取决于通过在另一个容器中添加一些组件或容器而创建的组件树(这是在Swing上创建任何应用程序接口时所做的基本操作)。

As you know - the whole idea of single thread for interface updates (its EDT in Swing) is about keeping each separate component visual updates (and its events) in a queue and perform them one by one inside that thread. That is needed mainly to avoid painting problems since every component inside single frame is painted to the single image that is kept in memory. The painting order is strict there so one component won't overwrite another on the final image. Painting order depends on the components tree that is created by adding some components or containers inside another container (that is a basic thing you do when creating any application interface on Swing).

总结一下 - 你必须在EDT中保留所有可视更新(可能导致它们的方法/操作)。还有其他任何可能在EDT之外完成 - 例如,你可以在EDT之外准备应用程序界面(再次,除非你在已经可见的容器中添加/删除/移动组件)。

To summ up - you must keep all visual updates (methods/operations that might cause them) inside the EDT. Anything else might be done outside the EDT - for example you can prepare the application interface outside the EDT (again, unless you add/remove/move component inside an already visible container).

在一些非常非常罕见的情况下,仍然可能存在一些内部问题。很久以前在这里对这个问题进行了很好的讨论:

http://www.velocityreviews.com/forums/t707173-why-does-jdk-1-6-recommend-creating-wing -components-on-the-edt.html

Still there might be some internal problems with that in some very very very rare cases. There was a good discussion of that question a long ago here:
http://www.velocityreviews.com/forums/t707173-why-does-jdk-1-6-recommend-creating-swing-components-on-the-edt.html

简而言之:自第6个JDK版本Sun在文档中声明甚至Swing组件创建应该在里面完成EDT以避免可能的问题。由于在创建组件时发生的事件,它们可能会出现在某些特定情况下创建大量接口。

To be short: since 6th JDK version Sun stated in docs that even Swing components creation should be done inside EDT to avoid possible problems. They might appear in some specific cases with heavy interfaces creation due to the events which occurs while the components are bing created.

无论如何,我会说在某些情况下你可能会在EDT之外创建您的界面,以避免加载器/应用程序卡住。在其他情况下,如果应用程序因接口创建时间而停留无关紧要 - 您应该使用EDT。我不能说更具体的事情,因为一切都取决于你的情况......

Anyway, i'd say that in some cases you might create your interface outside the EDT to avoid loader/application being stuck. In other cases, when it doesn't matter if application is stuck for the interface creation time - you should use EDT. And i cannot say anything more specific since everything depends on your case...

这篇关于在java中显示Gif动画的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆