我正在尝试制作一个程序来使用Tkinter显示动画GIF。这是我最初使用的代码:
from __future__ import division # Just because division doesn't work right in 2.7.4
from Tkinter import *
from PIL import Image,ImageTk
import threading
from time import sleep
def anim_gif(name):
## Returns { 'frames', 'delay', 'loc', 'len' }
im = Image.open(name)
gif = { 'frames': [],
'delay': 100,
'loc' : 0,
'len' : 0 }
pics = []
try:
while True:
pics.append(im.copy())
im.seek(len(pics))
except EOFError: pass
temp = pics[0].convert('RGBA')
gif['frames'] = [ImageTk.PhotoImage(temp)]
temp = pics[0]
for item in pics[1:]:
temp.paste(item)
gif['frames'].append(ImageTk.PhotoImage(temp.convert('RGBA')))
try: gif['delay'] = im.info['duration']
except: pass
gif['len'] = len(gif['frames'])
return gif
def ratio(a,b):
if b < a: d,c = a,b
else: c,d = a,b
if b == a: return 1,1
for i in reversed(xrange(2,int(round(a / 2)))):
if a % i == 0 and b % i == 0:
a /= i
b /= i
return (int(a),int(b))
class App(Frame):
def show(self,image=None,event=None):
self.display.create_image((0,0),anchor=NW,image=image)
def animate(self,event=None):
self.show(image=self.gif['frames'][self.gif['loc']])
self.gif['loc'] += 1
if self.gif['loc'] == self.gif['len']:
self.gif['loc'] = 0
if self.cont:
threading.Timer((self.gif['delay'] / 1000),self.animate).start()
def kill(self,event=None):
self.cont = False
sleep(0.1)
self.quit()
def __init__(self,master):
Frame.__init__(self,master)
self.grid(row=0,sticky=N+E+S+W)
self.rowconfigure(1,weight=2)
self.rowconfigure(3,weight=1)
self.columnconfigure(0,weight=1)
self.title = Label(self,text='No title')
self.title.grid(row=0,sticky=E+W)
self.display = Canvas(self)
self.display.grid(row=1,sticky=N+E+S+W)
self.user = Label(self,text='Posted by No Username')
self.user.grid(row=2,sticky=E+W)
self.comment = Text(self,height=4,width=40,state=DISABLED)
self.comment.grid(row=3,sticky=N+E+S+W)
self.cont = True
self.gif = anim_gif('test.gif')
self.animate()
root.protocol("WM_DELETE_WINDOW",self.kill)
root = Tk()
root.rowconfigure(0,weight=1)
root.columnconfigure(0,weight=1)
app = App(root)
app.mainloop()
try: root.destroy()
except: pass
test.gif是以下GIF:
这可以正常工作,但是GIF的质量很糟糕。我尝试将其更改为以下内容:
def anim_gif(name):
## Returns { 'frames', 'delay', 'loc', 'len' }
im = Image.open(name)
gif = { 'frames': [],
'delay': 100,
'loc' : 0,
'len' : 0 }
pics = []
try:
while True:
gif['frames'].append(im.copy())
im.seek(len(gif['frames']))
except EOFError: pass
try: gif['delay'] = im.info['duration']
except: pass
gif['len'] = len(gif['frames'])
return gif
class App(Frame):
def show(self,image=None,event=None):
can_w = self.display['width']
can_h = self.display['height']
pic_w,pic_h = image.size
rat_w,rat_h = ratio(pic_w,pic_h)
while pic_w > int(can_w) or pic_h > int(can_h):
pic_w -= rat_w
pic_h -= rat_h
resized = image.resize((pic_w,pic_h))
resized = ImageTk.PhotoImage(resized)
self.display.create_image((0,0),anchor=NW,image=resized)
但是,这偶尔会闪烁图像。虽然图片看起来不错,但是作为程序却毫无用处。我究竟做错了什么?
首先,您要为每个帧创建一个新的画布对象。最终,您将有成千上万的图像相互叠加。这是非常低效的;当您开始具有数千个对象时,canvas小部件会出现性能问题。
与其在画布上创建新的图像对象,不如使用画布的itemconfig方法重新配置现有对象。
其次,对于这样一个简单的任务,您不需要复杂的线程处理。在tkinter中有一个众所周知的用于制作动画的模式:绘制一帧,然后after
在将来使用该函数进行调用。
像这样:
def animate(self):
if self._image_id is None:
self._image_id = self.display.create_image(...)
else:
self.itemconfig(self._image_id, image= the_new_image)
self.display.after(self.gif["delay"], self.animate)
最后,除非有严格的理由使用画布,否则可以通过使用Label小部件来进一步降低复杂性。
问题内容: 我想使用python3和tkinter创建一个虚拟的宠物风格游戏。到目前为止,我已经有了主窗口并开始放入标签,但是我遇到的问题是播放动画gif。我在这里搜索并找到了一些答案,但是他们不断抛出错误。我发现使用PhotoImage的结果具有gif的索引位置,并在一定范围内继续。 当我在终端中使用“ pyhton3 main.py”运行此命令时,出现以下错误: _tkinter.TclErr
问题内容: 您好,我正在使用Swing在Java 1.6上编写GUI应用程序。 我有一个弹出屏幕,该窗口在加载Swing gui时以及稍后会显示gif动画。 我的弹出屏幕是一个JDialog。动画应显示在通过以下方式添加到Jdialog的JLabel上: 现在的事情是,动画仅在gui加载后显示。我相信在GUI加载时(这是我的应用程序中的繁重操作),EDT太忙了,无法运行动画。 现在的问题是,将GU
我正在尝试通过像往常一样将图像添加到来显示动画png(称为)。这适用于普通的-动画,但是,我更希望能够支持。 我一直在网上搜索现有的框架或解决方案,一无所获。有人找到在Swing中显示动画pngs的方法了吗? 要了解我为什么要实现,请查看以下示例,其中演示了GIF的局限性:http://jsfiddle.net/RUX8w/(您的浏览器必须支持apng!
这是一个非常基本的程序,我想用它来制作两个移动的球,但实际上只有一个在移动。 我也尝试过一些变化,但无法让第二个球移动;另一个相关问题-一些人使用方法来实现这一点,而其他人则执行然后重新绘制。我应该使用哪一个?为什么? 这是我的代码,它只设置/移动一个球的动画:
问题内容: 我想在应用程序中显示GIF动画图像。我发现,Android本身并不支持动画GIF的困难方式。 但是,它可以使用AnimationDrawable显示动画: 开发>指南>图像和图形> Drawables概述 该示例使用在应用程序资源中另存为帧的动画,但是我需要直接显示动画gif。 我的计划是将动画GIF分解为帧,并将每个帧作为可绘制对象添加到AnimationDrawable中。 有谁知
在你把我和另一个类似的问题联系起来之前,比如这个或那个。我要说的是,我完全按照答案所说的做了,但我的gif不会像它应该做的那样动画化(尽管它是显示出来的)。 下面是我在一个函数中所做的操作,该函数通过主应用程序函数堆栈显示。导航容器和堆栈中的屏幕。导航器。(我使用React导航在屏幕上移动,这里的上下文是按下一个按钮,它显示DetailsScreen函数的内容) 这将显示我的gif的第一个静态图像