Python添加時(shí)間軸以實(shí)現(xiàn)動(dòng)態(tài)繪圖詳解
時(shí)間軸
三維并不是人類理解的極限,畢竟我們生活在思維時(shí)空中。所以接下來(lái)要做的,就是四維圖形——加一個(gè)時(shí)間軸。
實(shí)際上,這個(gè)項(xiàng)目創(chuàng)建之初就已經(jīng)考慮到動(dòng)圖繪制的問(wèn)題,畢竟默認(rèn)的繪圖坐標(biāo)是txyz。但是,如果想實(shí)現(xiàn)動(dòng)圖繪制,就必須要先設(shè)置一個(gè)額外的線程,用于動(dòng)態(tài)更新圖像,否則繪圖循環(huán)壓迫主進(jìn)程,會(huì)導(dǎo)致界面變得奇卡無(wú)比。
接下來(lái),就開始實(shí)現(xiàn)繪制動(dòng)圖的需求,第一步,繪制UI。先在setFrmCtrl中添加
# 動(dòng)畫控制 frm = ttk.Frame(frmCtrl, width=320) frm.pack(side=tk.TOP, fill=tk.X) self.setAnimateFrame(frm)
然后實(shí)現(xiàn)具體的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="延時(shí)/毫秒").pack(**pDct)
ttk.Entry(frm, width=5, textvariable=self.aniDelay).pack(**pDct)
self.aniFrameNum = tk.StringVar()
self.aniFrameNum.set(100)
ttk.Label(frm, text="幀數(shù)").pack(**pDct)
ttk.Entry(frm, width=5, textvariable=self.aniFrameNum).pack(**pDct)
self.tIndex = 0 # 當(dāng)前幀數(shù)
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
延時(shí)表示當(dāng)自動(dòng)繪制動(dòng)圖時(shí),兩幀間隔時(shí)間;幀數(shù)表示總共繪制的時(shí)間個(gè)數(shù)。三個(gè)按鈕,分別用于向前一幀、向后一幀以及動(dòng)態(tài)播放。
單幀跳轉(zhuǎn)
坐標(biāo)t的工作原理和xyz并不相同,畢竟每次調(diào)用時(shí)間參數(shù)的時(shí)候,都只需要調(diào)用某一點(diǎn)的時(shí)間。所以,現(xiàn)有的設(shè)置坐標(biāo)數(shù)據(jù)的方法就不適用了,需要更改readDatas函數(shù)
# 讀取坐標(biāo)軸al的數(shù)據(jù)
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然后再更新一下繪圖函數(shù):其實(shí)只是取消t作為繪圖坐標(biāo)軸的地位
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()最后,實(shí)現(xiàn)一下btnNextFrame
def btnNextFrame(self):
num = int(self.aniFrameNum.get())
self.tIndex = (self.tIndex + 1) % num
self.btnDrawImg()效果如下,至此,我們離自動(dòng)化動(dòng)態(tài)繪圖,只剩下一個(gè)多線程了。

源代碼
本文只更改了ds.py中的源代碼,其他代碼可查看這篇博客:定制風(fēng)格的繪圖系統(tǒng)
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("數(shù)據(jù)展示工具")
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 = ("點(diǎn)線圖", "散點(diǎn)圖", "條形圖")
self.drawDct = {
"點(diǎn)線圖" : self.drawPlot,
"散點(diǎn)圖" : self.drawScatter,
"條形圖" : self.drawBar
}
# ! 設(shè)置
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)
# 動(dòng)畫控制
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)
# ! 動(dòng)畫控制
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="延時(shí)/毫秒").pack(**pDct)
ttk.Entry(frm, width=5, textvariable=self.aniDelay).pack(**pDct)
self.aniFrameNum = tk.IntVar()
self.aniFrameNum.set(100)
ttk.Label(frm, text="幀數(shù)").pack(**pDct)
ttk.Entry(frm, width=5, textvariable=self.aniFrameNum).pack(**pDct)
self.tIndex = 0 # 當(dāng)前幀數(shù)
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()
# 添加一組坐標(biāo)系
def addLast(self, evt):
title = f"坐標(biāo){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)
# 刪除一組坐標(biāo)系
def deleteLast(self, evt):
self.als[-1].pack_forget()
del self.als[-1]
# 加載數(shù)據(jù) // 暫時(shí)處于棄用狀態(tài)
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, "外部導(dǎo)入")
self.data[flag] = self.AL.setData(flag, data = data[:,i])
# 讀取坐標(biāo)軸al的數(shù)據(jù)
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
# 設(shè)置繪圖坐標(biāo)
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]
# 單幀繪圖函數(shù)
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添加時(shí)間軸以實(shí)現(xiàn)動(dòng)態(tài)繪圖詳解的詳細(xì)內(nèi)容,更多關(guān)于Python動(dòng)態(tài)繪圖的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Pygame游戲開發(fā)之太空射擊實(shí)戰(zhàn)碰撞改進(jìn)篇
相信大多數(shù)8090后都玩過(guò)太空射擊游戲,在過(guò)去游戲不多的年代太空射擊自然屬于經(jīng)典好玩的一款了,今天我們來(lái)自己動(dòng)手實(shí)現(xiàn)它,在編寫學(xué)習(xí)中回顧過(guò)往展望未來(lái),在本課中,我們將討論如何更改?Pygame?處理精靈之間沖突的方式2022-08-08
Python requests.post方法中data與json參數(shù)區(qū)別詳解
這篇文章主要介紹了Python requests.post方法中data與json參數(shù)區(qū)別詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-04-04
利用Anaconda完美解決Python 2與python 3的共存問(wèn)題
Anaconda 是 Python 的一個(gè)發(fā)行版,如果把 Python 比作 Linux,那么 Anancoda 就是 CentOS 或者 Ubuntu,下面這篇文章主要給大家介紹了利用Anaconda完美解決Python 2與python 3共存問(wèn)題的相關(guān)資料,文中介紹的非常詳細(xì),需要的朋友可以參考借鑒。2017-05-05
Python本地cache不當(dāng)使用導(dǎo)致內(nèi)存泄露的問(wèn)題分析與解決
最近在項(xiàng)目開發(fā)中遇到了本地cache不當(dāng)使用導(dǎo)致的一個(gè)內(nèi)存泄露問(wèn)題,所以本文主要分析了問(wèn)題出現(xiàn)的原因已經(jīng)解決方法,需要的小伙伴可以參考下2023-08-08
使用python實(shí)現(xiàn)回文數(shù)的四種方法小結(jié)
今天小編就為大家分享一篇使用python實(shí)現(xiàn)回文數(shù)的四種方法小結(jié),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-11-11
淺析python中while循環(huán)和for循環(huán)
在本篇文章里小編給各位整理的是關(guān)于python中while和for循環(huán)知識(shí)點(diǎn)詳解,有興趣的朋友們可以學(xué)習(xí)下。2019-11-11
python 使用tkinter+you-get實(shí)現(xiàn)視頻下載器
這篇文章主要介紹了python 使用tkinter+you-get實(shí)現(xiàn)視頻下載器,幫助大家方便的下載視頻資源,感興趣的朋友可以了解下2020-11-11
Python爬取阿拉丁統(tǒng)計(jì)信息過(guò)程圖解
這篇文章主要介紹了Python爬取阿拉丁統(tǒng)計(jì)信息過(guò)程圖解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-05-05

