Python添加时间轴以实现动态绘图详解

 更新时间:2023年09月17日 09:09:21   作者:微小冷  
这篇文章主要为大家详细介绍了Python如何添加时间轴以实现动态绘图,文中的示例代码讲解详细,具有一定的学习价值,感兴趣的小伙伴可以参考一下

时间轴

三维并不是人类理解的极限,毕竟我们生活在思维时空中。所以接下来要做的,就是四维图形——加一个时间轴。

实际上,这个项目创建之初就已经考虑到动图绘制的问题,毕竟默认的绘图坐标是txyz。但是,如果想实现动图绘制,就必须要先设置一个额外的线程,用于动态更新图像,否则绘图循环压迫主进程,会导致界面变得奇卡无比。

接下来,就开始实现绘制动图的需求,第一步,绘制UI。先在setFrmCtrl中添加

# 动画控制
frm = ttk.Frame(frmCtrl, width=320)
frm.pack(side=tk.TOP, fill=tk.X)
self.setAnimateFrame(frm)

然后实现具体的self.setAnimateFrame

def setAnimateFrame(self, frm):
    pDct = dict(side=tk.LEFT, fill=tk.X, padx=2)
    self.aniDelay = tk.StringVar()
    self.aniDelay.set(100)
    ttk.Label(frm, text="延时/毫秒").pack(**pDct)
    ttk.Entry(frm, width=5, textvariable=self.aniDelay).pack(**pDct)
    self.aniFrameNum = tk.StringVar()
    self.aniFrameNum.set(100)
    ttk.Label(frm, text="帧数").pack(**pDct)
    ttk.Entry(frm, width=5, textvariable=self.aniFrameNum).pack(**pDct)
    self.tIndex = 0   # 当前帧数
    ttk.Button(frm, width=3, text=  "⇦", 
        command=self.btnPreFrame).pack(**pDct)
    ttk.Button(frm, width=3, text="▶", 
        command=self.btnAniStart).pack(**pDct)
    ttk.Button(frm, width=3, text="⇨", 
        command=self.btnNextFrame).pack(**pDct)
def btnAniStart(self): pass
def btnPreFrame(self): pass
def btnNextFrame(self): pass

延时表示当自动绘制动图时,两帧间隔时间;帧数表示总共绘制的时间个数。三个按钮,分别用于向前一帧、向后一帧以及动态播放。

单帧跳转

坐标t的工作原理和xyz并不相同,毕竟每次调用时间参数的时候,都只需要调用某一点的时间。所以,现有的设置坐标数据的方法就不适用了,需要更改readDatas函数

# 读取坐标轴al的数据
def readDatas(self, al):
    dct = {}
    data = {}
    for flag in self.drawTypeDim.getDim():
        data[flag] = al.setData(flag, **dct)
        if flag=='t': 
            dct['t'] = data['t'][self.tIndex]
        else:
            dct[flag] = data[flag]
    return data

然后再更新一下绘图函数:其实只是取消t作为绘图坐标轴的地位

def btnDrawImg(self):
    self.fig.clf()
    self.axDct = {}
    for al in self.als:
        ax = self.setDrawAxis(al)
        data = self.readDatas(al)
        draw = self.drawDct[al.getDrawType()]
        style = al.getStyle()
        keys = al.getDrawDim().replace('t',"")
        draw(ax, data, keys, style)
    self.fig.subplots_adjust(left=0.1, right=0.95, top=0.95, bottom=0.08)
    self.canvas.draw()

最后,实现一下btnNextFrame

def btnNextFrame(self): 
    num = int(self.aniFrameNum.get())
    self.tIndex = (self.tIndex + 1) % num
    self.btnDrawImg()

效果如下,至此,我们离自动化动态绘图,只剩下一个多线程了。

源代码

本文只更改了ds.py中的源代码,其他代码可查看这篇博客:定制风格的绘图系统

import tkinter as tk
import tkinter.ttk as ttk
from tkinter.filedialog import askopenfilename
import matplotlib
import matplotlib as mpl
mpl.use('TkAgg')
import matplotlib.backends.backend_tkagg as mbb
from matplotlib.figure import Figure
import numpy as np
from alist import AxisList
from base import DrawType
class DarwSystem():
    def __init__(self):
        self.root = tk.Tk()
        self.root.title("数据展示工具")
        self.data = {}
        self.als = []
        self.initConst()
        self.setFrmCtrl()
        frmFig = ttk.Frame(self.root)
        frmFig.pack(side=tk.LEFT,fill=tk.BOTH,expand=tk.YES)
        self.setFrmFig(frmFig)
        self.root.mainloop()
    def initConst(self):
        self.TYPES = ("点线图", "散点图", "条形图")
        self.drawDct = {
            "点线图" : self.drawPlot,
            "散点图" : self.drawScatter,
            "条形图" : self.drawBar
        }
    # ! 设置
    def setFrmCtrl(self):
        frmCtrl = ttk.Frame(self.root,width=320)
        frmCtrl.pack(side=tk.RIGHT, fill=tk.Y)
        # 主控Frame
        frm = ttk.Frame(frmCtrl, width=320)
        frm.pack(side=tk.TOP, fill=tk.X)
        self.setCtrlButtons(frm)
        # 动画控制
        frm = ttk.Frame(frmCtrl, width=320)
        frm.pack(side=tk.TOP, fill=tk.X)
        self.setAnimateFrame(frm)
        self.frmAxis = ttk.Frame(frmCtrl)
        self.frmAxis.pack(side=tk.TOP, fill=tk.X)
        self.addLast(None)
    # ! 工具栏
    def setCtrlButtons(self, frm):
        self.drawTypeDim = DrawType(frm)
        self.drawTypeDim.pack(side=tk.LEFT)
        ttk.Button(frm, text="📈",width=3,
            command=self.btnDrawImg).pack(side=tk.LEFT)
        ttk.Button(frm, text="📂",width=3,
            command=self.btnLoadData).pack(side=tk.LEFT)
        btn = ttk.Button(frm, text="+", width=3)
        btn.pack(side=tk.LEFT)
        btn.bind("<Button-1>", self.addLast)
        btn = ttk.Button(frm, text="-", width=3)
        btn.pack(side=tk.LEFT)
        btn.bind("<Button-1>", self.deleteLast)
    # ! 动画控制
    def setAnimateFrame(self, frm):
        pDct = dict(side=tk.LEFT, fill=tk.X, padx=2)
        self.aniDelay = tk.IntVar()
        self.aniDelay.set(100)
        ttk.Label(frm, text="延时/毫秒").pack(**pDct)
        ttk.Entry(frm, width=5, textvariable=self.aniDelay).pack(**pDct)
        self.aniFrameNum = tk.IntVar()
        self.aniFrameNum.set(100)
        ttk.Label(frm, text="帧数").pack(**pDct)
        ttk.Entry(frm, width=5, textvariable=self.aniFrameNum).pack(**pDct)
        self.tIndex = 0   # 当前帧数
        ttk.Button(frm, width=3, text=  "⇦", 
            command=self.btnPreFrame).pack(**pDct)
        ttk.Button(frm, width=3, text="▶", 
            command=self.btnAniStart).pack(**pDct)
        ttk.Button(frm, width=3, text="⇨", 
            command=self.btnNextFrame).pack(**pDct)
    def btnAniStart(self): pass
    def btnPreFrame(self): pass
    def btnNextFrame(self): 
        num = self.aniFrameNum.get()
        self.tIndex = (self.tIndex + 1) % num
        self.btnDrawImg()
    # 添加一组坐标系
    def addLast(self, evt):
        title = f"坐标{len(self.als)}"
        al = AxisList(self.frmAxis, title, 1, [5,10,30], 
            self.TYPES, self.drawTypeDim.getDct())
        al.pack(side=tk.TOP, fill=tk.X)
        self.als.append(al)
    # 删除一组坐标系
    def deleteLast(self, evt):
        self.als[-1].pack_forget()
        del self.als[-1]
    # 加载数据 // 暂时处于弃用状态
    def btnLoadData(self):
        name = askopenfilename()
        data = np.genfromtxt(name)
        for i, flag in enumerate('xyz'):
            if i >= data.shape[1]:
                return
            self.AL.setOneMode(flag, "外部导入")
            self.data[flag] = self.AL.setData(flag, data = data[:,i])
    # 读取坐标轴al的数据
    def readDatas(self, al):
        dct = {}
        data = {}
        for flag in al.getDrawDim():
            data[flag] = al.setData(flag, **dct)
            if flag=='t': 
                dct['t'] = data['t'][self.tIndex]
            else:
                dct[flag] = data[flag]
        return data
    # 设置绘图坐标
    def setDrawAxis(self, al):
        sub = int(al.getSub())
        print(sub)
        if sub in self.axDct:
            return self.axDct[sub]
        p = al.getProj() 
        if p == "None":
            self.axDct[sub] = self.fig.add_subplot(sub)
        else:
            self.axDct[sub] = self.fig.add_subplot(sub, projection=p)
        return self.axDct[sub]
    # 单帧绘图函数
    def btnDrawImg(self):
        self.fig.clf()
        self.axDct = {}
        for al in self.als:
            ax = self.setDrawAxis(al)
            data = self.readDatas(al)
            draw = self.drawDct[al.getDrawType()]
            style = al.getStyle()
            keys = al.getDrawDim().replace('t',"")
            draw(ax, data, keys, style)
        self.fig.subplots_adjust(left=0.1, right=0.95, top=0.95, bottom=0.08)
        self.canvas.draw()
    def drawBar(self, ax, data, keys, style):
        ax.bar(data['x'], data['y'])
    def drawPlot(self, ax, data, keys, style):
        ax.plot(*[data[key] for key in keys], **style)
    def drawScatter(self, ax, data, keys, style):
        ax.scatter(*[data[key] for key in keys])
    def setFrmFig(self, frmFig):
        self.fig = Figure()
        self.canvas = mbb.FigureCanvasTkAgg(self.fig,frmFig)
        self.canvas.get_tk_widget().pack(
            side=tk.TOP,fill=tk.BOTH,expand=tk.YES)
        self.toolbar = mbb.NavigationToolbar2Tk(self.canvas,frmFig,
            pack_toolbar=False)
        self.toolbar.update()
        self.toolbar.pack(side=tk.RIGHT)
if __name__ == "__main__":
    test = DarwSystem()

以上就是Python添加时间轴以实现动态绘图详解的详细内容,更多关于Python动态绘图的资料请关注脚本之家其它相关文章!

相关文章

  • Python中hashlib模块的摘要算法详解

    Python中hashlib模块的摘要算法详解

    这篇文章主要介绍了Python中hashlib模块的摘要算法详解,摘要算法又称哈希算法、散列算法,它通过一个函数,把任意长度的数据转换为一个长度固定的数据串,通常用16进制的字符串表示,需要的朋友可以参考下
    2023-08-08
  • 记一次Django响应超慢的解决过程

    记一次Django响应超慢的解决过程

    这篇文章主要介绍了记一次Django响应超慢的解决过程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-09-09
  • python 处理微信对账单数据的实例代码

    python 处理微信对账单数据的实例代码

    本文通过实例代码给大家介绍了python 处理微信对账单数据,代码简单易懂,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-07-07
  • 教你如何在Django 1.6中正确使用 Signal

    教你如何在Django 1.6中正确使用 Signal

    因为新的django开发人员得知signal之后, 往往会很高兴去使用它. 他们在能使用signal的地方就使用signal, 并且这是他们觉得自己是django专家一样. 然而, 像这样编码一段时间后, django项目就会变得异常复杂, 许多内容都纠结在一起无法解开.
    2014-06-06
  • tensorflow 获取模型所有参数总和数量的方法

    tensorflow 获取模型所有参数总和数量的方法

    今天小编就为大家分享一篇tensorflow 获取模型所有参数总和数量的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-06-06
  • python实现简单遗传算法

    python实现简单遗传算法

    这篇文章主要介绍了python如何实现简单遗传算法,帮助大家更好的利用python进行数据分析,感兴趣的朋友可以了解下
    2020-09-09
  • python3+PyQt5 实现Rich文本的行编辑方法

    python3+PyQt5 实现Rich文本的行编辑方法

    今天小编就为大家分享一篇python3+PyQt5 实现Rich文本的行编辑方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-06-06
  • Python实现SMTP发送邮件详细教程

    Python实现SMTP发送邮件详细教程

    这篇文章主要为大家详细介绍了Python实现SMTP发送邮件详细教程,附SMTP邮件发送代码,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-08-08
  • Django 后台获取文件列表 InMemoryUploadedFile的例子

    Django 后台获取文件列表 InMemoryUploadedFile的例子

    今天小编就为大家分享一篇Django 后台获取文件列表 InMemoryUploadedFile的例子,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-08-08
  • python高温预警数据获取实例

    python高温预警数据获取实例

    这篇文章主要为大家介绍了利用python获取高温数据进行高温预警的防护措施,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-07-07

最新评论