您好,我正在使用Swing在Java 1.6上编写GUI应用程序。
我有一个弹出屏幕,该窗口在加载Swing gui时以及稍后会显示gif动画。
我的弹出屏幕是一个JDialog。动画应显示在通过以下方式添加到Jdialog的JLabel上:
ImageIcon myImgIcon = getMyImgIcon();
JLabel imageLbl = new JLabel(myImgIcon);
add(imageLbl, BorderLayout.CENTER);
现在的事情是,动画仅在gui加载后显示。我相信在GUI加载时(这是我的应用程序中的繁重操作),EDT太忙了,无法运行动画。
现在的问题是,将GUI加载到其他线程(而不是EDT)上对我来说是错误的,因此我不知道如何解决该问题。
有人有主意吗?
您只需要释放一些繁重任务的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)的整体思想是将每个单独的组件 可视
更新(及其事件)保留在队列中,并在该线程中一个接一个地执行它们。这主要是为了避免绘画问题,因为单个帧内的每个组件都被绘画为保存在内存中的 单个
图像。那里的绘画顺序很严格,因此一个组件不会在最终图像上覆盖另一个组件。绘制顺序取决于通过在另一个容器内添加一些组件或容器而创建的组件树(这是在Swing上创建任何应用程序接口时要做的基本操作)。
总结-您必须将所有 视觉 更新(可能导致它们的方法/操作)保留在EDT中。还有什么 可能 的EDT外完成-
例如,你可以准备EDT以外的应用程序接口(同样,除非你添加一个已经可以看到容器内/删除/移动组件)。
在某些非常非常罕见的情况下,仍然可能存在一些内部问题。很久以前,这里对这个问题进行了很好的讨论:http :
//www.velocityreviews.com/forums/t707173-why-does-jdk-1-6-recommend-creating-
swing-components-on-the-edt
.html
简而言之:自从第6个JDK版本以来,Sun在文档中指出,即使Swing组件创建也应在EDT内部完成,以避免 可能的
问题。在某些特定情况下,由于创建组件时发生的事件,它们可能会在创建大量接口的情况下出现。
无论如何,我会说在某些情况下,您可以在EDT外部创建接口,以避免加载程序/应用程序卡住。在其他情况下,当应用程序在接口创建时间内是否卡住并不重要-
您应该使用EDT。我不能说更具体的事情,因为一切都取决于您的情况。
问题内容: 我想在应用程序中显示GIF动画图像。我发现,Android本身并不支持动画GIF的困难方式。 但是,它可以使用AnimationDrawable显示动画: 开发>指南>图像和图形> Drawables概述 该示例使用在应用程序资源中另存为帧的动画,但是我需要直接显示动画gif。 我的计划是将动画GIF分解为帧,并将每个帧作为可绘制对象添加到AnimationDrawable中。 有谁知
问题内容: 我正在尝试制作一个程序来使用Tkinter显示动画GIF。这是我最初使用的代码: test.gif是以下GIF: 这可以正常工作,但是GIF的质量很糟糕。我尝试将其更改为以下内容: 但是,这偶尔会闪烁图像。虽然图片看起来不错,但是作为程序却毫无用处。我究竟做错了什么? 问题答案: 首先,您要为每个帧创建一个新的画布对象。最终,您将有成千上万的图像相互叠加。这是非常低效的;当您开始具有数
在你把我和另一个类似的问题联系起来之前,比如这个或那个。我要说的是,我完全按照答案所说的做了,但我的gif不会像它应该做的那样动画化(尽管它是显示出来的)。 下面是我在一个函数中所做的操作,该函数通过主应用程序函数堆栈显示。导航容器和堆栈中的屏幕。导航器。(我使用React导航在屏幕上移动,这里的上下文是按下一个按钮,它显示DetailsScreen函数的内容) 这将显示我的gif的第一个静态图像
它与文件一起工作很好,但是当我使用文件时,它是空的。我在某处读到了将重命名为,但它只显示一帧动画gif而没有动画。有什么想法吗?
我第一次使用Glide在ImageView中显示GIF。我已经按照几个站点的方式对其进行了编码。但它不起作用。我已经给出了以下所有代码:(如果我弄错了什么,请告诉我) 项目级build.gradle 应用程序级构建。gradle文件: activity_main.xml 活动Java代码: 单击“提交”按钮后,我没有看到GIF图像。
问题内容: 我想在UIImageView中使用gif,但不能。我的代码是: 迅速: 在客观CI中有animationImageWithAnimatedGIFData,但是很快我不知道怎么称呼它,或者不存在。 谢谢! 问题答案: 我假设您使用的是https://github.com/mayoff/uiimage-from-animated- gif ,源代码在Objective-C中。 您首先需要将