python 实现 tkinter.Label、Button 加载 gif 动态图

python 实现 tkinter.Label、Button 加载 gif 动态图,让界面变得更美丽!

在网上转了一圈,发现 Label 加载的图均是静止的,就是加载 gif 的动态图,都只是显示第一帧的静图。

原理也很简单,就是把 gif 动态图分解成多帧的单图逐帧显示,最后软件关闭时再删除掉临时分解的图片,我写了个 GIF的模块,大家可以直接使用

不费话了,直接上代码:

# -*-coding:utf-8 -*-
"""
GIF 动画文件播放模块
能配合 tkinter.Label 组件播放动态图

实现原理:将gif 动太按帧数分解成独立临时图片,再分别显示
最后再删除临时图片
    """

import tkinter
from PIL import Image,ImageTk
from PIL import ImageSequence
import random #随机模块
import os,sys # 系统模块

STR_FRAME_FILENAME="frame{}.png" #每帧图片的文件名格式

class playGif():
    def __init__(self,file,temporary=""):#temporary 指临时目录路径,为空时则随机生成
        self.__strPath=file
        self.__index=1 #当前显示图片的帧数

        if len(temporary)==0:
            self.strTemporaryFolder=self.crearteTemporaryFolder() #随机得到临时目录
        else:
            self.strTemporaryFolder=temporary #指定的临时目录
        
        self.__intCount=0  #gif 文件的帧数
        
        self.decomposePics() #开始分解
        
        #
    def crearteTemporaryFolder(self):#生成临时目录名返回
        # 获取当前调用模块主程序的运行目录
        strSelfPath=str(os.path.dirname(os.path.realpath(sys.argv[0])))
        if len(strSelfPath)==0:
            strSelfPath=os.path.join(os.getcwd())
            
        def createRandomFolder(strSelfPath):#内嵌方法,生成随机目录用
            length=random.randint(5,10)# 随机长度
            path=""
            for i in range(length):
                path=path+chr(random.randint(97,122)) #随机生成a-z字母
            
            return os.path.join(strSelfPath,path)
            #
        #获取当前软件目录
        
        folder=createRandomFolder(strSelfPath)
        while os.path.isdir(folder): #已存在
            folder=createRandomFolder(strSelfPath)
        
        return folder
        #
    def decomposePics(self):#分解 gif 文件的每一帧到独立的图片文件,存在临时目录中
        i = 0
        img = Image.open(self.__strPath)
        self.__width,self.__height=img.size #得到图片的尺寸
        
        os.mkdir(self.strTemporaryFolder) #创建临时目录
        for frame in ImageSequence.Iterator(img): #遍历每帧图片
            frame.save(os.path.join(self.strTemporaryFolder,STR_FRAME_FILENAME.format(i+1))) #保存独立图片
            i += 1
        
        self.__intCount=i #得到 gif 的帧数
        #
    def getPicture(self,frame=0):#返回第 frame 帧的图片(width=0,height=0)
        if frame==0:
            frame=self.__index
        elif frame>=self.__intCount:
            frame=self.__intCount #最后一张
            
        img=tkinter.PhotoImage(file=os.path.join(self.strTemporaryFolder,STR_FRAME_FILENAME.format(frame)))
        self.__index=self.getNextFrameIndex()
        
        return img #返回图片
    
        #
    def getNextFrameIndex(self,frame=0):#返回下一张的帧数序号
        if frame==0:
            frame=self.__index #按当前插入帧数
            
        if frame==self.__intCount:
            return 1 #返回第1张,即从新开始播放
        else:
            return frame + 1 #下一张
        #
    def playGif(self,tk,widget,time=100):#开始调用自身实现播放,time 单位为毫秒
        img=self.getPicture()
        widget.config(image=img)
        widget.image=img
        tk.after(time,self.playGif,tk,widget,time) # 在 time 时间后调用自身
        
        #
    def close(self):#关闭动画文件,删除临时文件及目录
        files=os.listdir(self.strTemporaryFolder)
        for file in files:
            os.remove(os.path.join(self.strTemporaryFolder,file))
            
        os.rmdir(self.strTemporaryFolder)
        
        #
        
if __name__ == "__main__":
    import tkinter

    def delete(): #删除临时图
        root.destroy()
        gif.close()
        
    file=r"D:\我的作品\Python\test\test.gif"
    root=tkinter.Tk()
    label=tkinter.Label(root,text="11",bg="#FFFFFF")
    label.pack(side=tkinter.LEFT)
    button=tkinter.Button(root)
    button.pack(side=tkinter.LEFT)
    root.protocol('WM_DELETE_WINDOW',delete)#####【重要】关闭窗口后的事件:delete
    
    gif=playGif(file)
    #label.config(image=gif.getPicture())
    
    gif.playGif(root,button) #实现动态插放
    
    root.mainloop()
    
  • 6
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jumpbull01

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值