wxpython编写的GUI中显示gif图片的另一种方法

发布时间 2023-04-01 16:05:20作者: No九五二七9527

当采用wx.adv.AnimationCtrl方法加载大尺寸gif图片出错的时候,就需要考虑用其他方式加载了;

这里用到了imageio.v3和numpy配合加载gif图片。代码实例如下。

注意的是,此代码并非gif加载全能的!当图片不规则还是会出现无法加载的情况(gif各帧之间大小不一,具体原因搞不懂);而且加载的gif图片大概率会出现频闪,经调试无果(技术太菜,代码是缝合的)。

import wx                            # 导入wxPython库
import imageio.v3 as iio             # 导入imageio库
import numpy as np                   # 导入numpy库

# 定义一个窗口类MyFrame,继承自wx.Frame类
class MyFrame(wx.Frame):
    def __init__(self, parent):
        # 调用父类构造函数,设置窗口的标题
        super().__init__(parent, title="GIF Display")
        
        # 初始化一个面板
        self.panel = wx.Panel(self)

        # 读取gif图片,并将其转化为numpy数组
        self.gif = iio.imread("Example002.gif")
        self.gif = [np.uint8(frame) for frame in self.gif]

        # 创建一个静态位图控件,用于显示gif图片
        self.gifCtrl = wx.StaticBitmap(self.panel, size=(self.gif[0].shape[1],self.gif[0].shape[0]))
        # 将第一帧设置为位图的初始值
        self.gifCtrl.SetBitmap(wx.Bitmap.FromBuffer(self.gif[0].shape[1], self.gif[0].shape[0], self.gif[0]))

        # 创建一个垂直方向的BoxSizer,用来布局gif图片控件
        vbox = wx.BoxSizer(wx.VERTICAL)
        vbox.AddStretchSpacer()
        vbox.Add(self.gifCtrl, 0, wx.CENTER)
        vbox.AddStretchSpacer()

        # 将BoxSizer设置为面板的布局管理器
        self.panel.SetSizer(vbox)

        # 添加计数器和定时器
        self.counter = 0
        self.timer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.onTimer)   # 将定时器事件绑定到onTimer函数上
        self.timer.Start(100)                  # 间隔设置为100毫秒

    def onTimer(self, event):
        """
        定时器触发事件,更新gif图片
        """
        self.counter += 1                    # 计数器自增1
        idx = self.counter % len(self.gif)    # 计算当前帧的下标,使用模运算实现循环播放
        # 更新位图控件的值
        self.gifCtrl.SetBitmap(wx.Bitmap.FromBuffer(self.gif[idx].shape[1], self.gif[idx].shape[0], self.gif[idx]))

    def onResize(self, event):
        """
        当窗口大小改变时,重新定位gif图片的位置
        """
        w, h = self.GetClientSize()               # 获取窗口客户区的宽度和高度
        gif_w, gif_h = self.gifCtrl.GetSize()     # 获取gif图片控件的宽度和高度
        # 设置gif图片控件的新位置
        self.gifCtrl.SetPosition(((w - gif_w) // 2, (h - gif_h) // 2))
        event.Skip()

# 应用程序入口
if __name__ == '__main__':
    app = wx.App()       # 初始化wxPython应用程序
    frame = MyFrame(None) # 创建一个MyFrame实例
    frame.Show()          # 显示窗口
    app.MainLoop()