用python做好看的动态图像,怎样用python绘制动图

大家好,本文将围绕用python做好看的动态图像展开说明,怎样用python绘制动图是一个很多人都想弄明白的事情,想搞清楚python制作动态数据图需要先了解以下几个事情。

前言
matplotlib中可以显示各种各种的图标,如折线、直方图、散点图、柱状图、饼图等,还可以显示3D图像,所以在很多场合都可以使用。

那么如果我们想要使图表动态化显示起来,该如何实现呢?
如下效果:
在这里插入图片描述
配置:
平台:windows
工具:visual studio code
语言:python
库:matplotlib、PyQt5

1、显示静态图表
用matplotlib显示一张图表非常简单,如下:

 def on_btn_chart1_click(self):  
        """显示图表"""
        fig,ax=plt.subplots()
        fig.suptitle('pic1')
        data=np.random.randn(100)
        self.ln=plt.plot(data)
        plt.show()

显示效果:
在这里插入图片描述
matplotlib利用subplots创建了一个Figure的实例,Figure就是用于显示图表或图像的窗口python用turtle画简单树形图
而plot产生了一个二维折线图表格式,折线图表的数据来自于numpy产生的随机数。

2、动态图表
如果我们要实现动态图表,其实有多种方式,因为matplotlib产生的图表其实就是一帧帧图片,麻烦的方式是我们用循环产生多张图片,然后将图片组合起来生成动画。
但matplotlib本身提供了直接产生动画的类,即Animation。

A base class for Animations.

This class is not usable as is, and should be subclassed to provide needed
behavior.

但是Animation不能直接用,它是一个基类,我们可以使用matplotlib提供的FuncAnimation类。

TimedAnimation subclass that makes an animation by repeatedly calling a function func.

Fun从Animation是在TimedAnimation的基础上,可以直接调用函数来更新数据。

#实例化Figure动画
        self.ani=FuncAnimation(self.fig,self.update,
                                frames=range(50),    
                                #init_func=self.init,
                                interval=100,
                                repeat=False,
                                blit=True)

如上,我们新建FuncAnimation的实例,注意其参数,我们一一解释下:
fig:即Figure,我们可以创建一个Figure,然后填入此参数
func:函数,即更新数据的函数,动态图表的每一帧图表的数据,由此函数返回,但注意,返回的不仅仅是数据,而是一个Artist:

artists : list
Each list entry is a collection of .Artist objects that are made visible on the corresponding frame. Other artists are made invisible.

比如本文中的示例中,我们返回的是matplotlib.plot()是折线数据:
大致如下:

list[Line2D]:  
    return gca().plot(
        *args,
        scalex=scalex,
        scaley=scaley,
        **({"data": data} if data is not None else {}),
        **kwargs,
    )

可以看到,其返回的是一个Line2D的数据格式。

  def update(self,frame):     
        """Figure图表更新数据"""
        
        print(frame)
        data=np.random.randn(100)
        self.ln=plt.plot(data)
        return self.ln

init_func:初始函数,这是可选项,即动画图表开始时的函数,其返回格式与func是一样的。

frames:
frames参数可以理解是动画中帧的数量,比如设置为一个整数50,那么在每一次间隔后,都会传递一个整数给func,传递的数字是当前帧的索引,通常情况是递增。如果设置了动画循环播放,那么在帧索引达到最大后又会从头开始。

frames: 可迭代对象、整数、生成器函数或None,可选

这是传递给func和动画每个帧的数据源。

如果是一个可迭代对象,那么只需使用提供的值。如果可迭代对象有长度,它将覆盖save_count关键字参数。

如果是一个整数,则等同于传递“range(frames)”。

如果是一个生成器函数,则必须具有以下签名:

def gen_function() -> obj

如果为None,则等同于传递“itertools.count”。

在所有这些情况下,frames中的值只是简单地传递给用户提供的func,因此可以是任何类型。

interval:动画间隔,默认为200ms,可以自定义。

repeat:标志位,如果设为True,则动画重复,反之,设为False即可。

blit:标志位,其作用如下:

在Matplotlib的FuncAnimation中,blit参数用于控制动画的绘制方式。Blit,全称为“位块传输”(bitmap block transfer),是一种图形处理技术,用于将一个图像的一部分拷贝到另一个位置。

当blit参数设置为True时,Matplotlib只会重新绘制那些改变的部分,而不是每次都重新绘制整个图像。这可以提高动画的绘制速度,特别是对于大规模数据集或复杂的图形。

然而,对于某些图形元素,如文本或线条,blit可能无法正确地更新它们。在这种情况下,你可能需要将blit设置为False,以便于Matplotlib能够正确地更新这些元素。

总的来说,选择是否使用blit取决于你的具体需求和图形的复杂性。在大多数情况下,使用blit可以提高动画的性能。

看一下启用blit和不启用blit的区别:
blit=True:
在这里插入图片描述
blit=False:
在这里插入图片描述
基本上就是以上参数,下面看一下完整程序:

import sys,os,time 

import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas 
from matplotlib.animation import FuncAnimation 

from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *

class Example(QWidget):
    def __init__(self):
        super().__init__()
        print(matplotlib.__version__)
        self.initUI()

    def initUI(self):
        
        layout=QVBoxLayout()
        self.setLayout(layout)
        
        self.btn0=QPushButton('开始动画',self)
        self.btn0.setGeometry(40,40,100,20)
        self.btn0.clicked.connect(self.on_btn0_click)
        
        self.btn1=QPushButton('停止',self)
        self.btn1.setGeometry(40,70,100,20)
        self.btn1.clicked.connect(self.on_btn1_click)
        
        self.btn2=QPushButton('继续',self)
        self.btn2.setGeometry(40,100,100,20)
        self.btn2.clicked.connect(self.on_btn2_click)
        
        self.btn_chart1=QPushButton('显示图表',self)
        self.btn_chart1.setGeometry(150,40,100,20)
        self.btn_chart1.clicked.connect(self.on_btn_chart1_click)
        
        
        #fig=plt.figure()
        #canvas=FigureCanvas(fig)
        #layout.addWidget(canvas)
        
      
        self.setWindowTitle('plot')
        self.setGeometry(300,300,600,400)
        self.show()
        
        matplotlib.rcParams['font.sans-serif'] = 'SimHei'  # 设置默认字体为黑体  
        matplotlib.rcParams['axes.unicode_minus'] = False  # 解决保存图像是负号'-'显示为方块的问题  
        
       
       
    def init(self):  
        """Figure图表初始参数"""
        #设置图像的X轴的范围
        self.ax.set_xlim(0, 2 * np.pi) 
        self.ax.set_ylim(-5,5)
        data=np.random.randn(500)
        self.ln=plt.plot(data)
        return self.ln
    
    def update(self,frame):
        """Figure图表更新数据"""
        
        print(frame)
        data=np.random.randn(100)
        self.ln=plt.plot(data)
        return self.ln
    
    def on_btn0_click(self,frame):
        
        self.fig, self.ax = plt.subplots() 
        #设置Figure的窗口标题
        self.fig.canvas.manager.set_window_title('动态化图表')
        #设置Figure中的图像的标题
        self.fig.suptitle('动态化图表')
        
        #实例化Figure动画
        self.ani=FuncAnimation(self.fig,self.update,
                                frames=50,
                                #init_func=self.init,
                                interval=100,
                                repeat=False,
                                blit=False)
        
        plt.show()
        #self.ani.save('AnyCAD-3DUI\\mymovie.mp4',fps=10)
        
    def on_btn2_click(self):
        """resume:继续动画"""
        try:
            self.ani.resume()
        except Exception as e:
            QMessageBox.warning(self,'警告',str(e))
    
    def on_btn1_click(self,frame):
        """pause:暂停动画"""
        try:
            self.ani.pause()
            
        except Exception as e:
            QMessageBox.warning(self,'警告',str(e))
            
    def on_btn_chart1_click(self):
        """显示图表"""
        fig,ax=plt.subplots()
        fig.suptitle('pic1')
        data=np.random.randn(100)
        self.ln=plt.plot(data)
        plt.show()
        
        
if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

注:说明一下,本文是笔者记录为以后涉及到相同问题时可作参考使用,但如果能对你有所帮助,那么也是极好的。

  • 18
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值