timeline
Three dimensions are not the limit of human understanding; after all, we live in thinking time and space. So the next thing to do is a four-dimensional graphic - add a timeline.
In fact, this project has been created with motion graphics in mind, after all, the default plotting coordinates are txyz. However, if you want to implement motion graphics, you must first set up an additional thread for dynamically updating the image, or else the plotting loop will oppress the main process, which will result in the interface becoming incredibly laggy.
Next, it's time to start realizing the need to draw motion graphics. the first step is to draw the UI. first add the setFrmCtrl to the
# Animation control frm = (frmCtrl, width=320) (side=, fill=) (frm)
Then implement the specific
def setAnimateFrame(self, frm): pDct = dict(side=, fill=, padx=2) = () (100) (frm, text="Delay/milliseconds").pack(**pDct) (frm, width=5, textvariable=).pack(**pDct) = () (100) (frm, text="Frames.").pack(**pDct) (frm, width=5, textvariable=).pack(**pDct) = 0 # Current frames (frm, width=3, text= "⇦", command=).pack(**pDct) (frm, width=3, text="▶", command=).pack(**pDct) (frm, width=3, text="⇨", command=).pack(**pDct) def btnAniStart(self): pass def btnPreFrame(self): pass def btnNextFrame(self): pass
Delay indicates the time between two frames when the motion picture is drawn automatically; Frame Count indicates the total number of drawing times. Three buttons for frame forward, frame backward and motion playback.
single-frame jump
Coordinate t doesn't work the same way as xyz, after all, each time the time parameter is called, it only needs to be called for a certain point in time. So, the existing method of setting the coordinate data doesn't work anymore, and you need to change the readDatas function
# Read the data from the axes al def readDatas(self, al): dct = {} data = {} for flag in (): data[flag] = (flag, **dct) if flag=='t': dct['t'] = data['t'][] else: dct[flag] = data[flag] return data
Then update the plotting function a bit more: it's really just a matter of removing t as the plotting axis
def btnDrawImg(self): () = {} for al in : ax = (al) data = (al) draw = [()] style = () keys = ().replace('t',"") draw(ax, data, keys, style) .subplots_adjust(left=0.1, right=0.95, top=0.95, bottom=0.08) ()
Finally, implement btnNextFrame.
def btnNextFrame(self): num = int(()) = ( + 1) % num ()
The result is as follows. At this point, we are just one multithread away from automating dynamic drawing.
source code (computing)
This article only changes the source code in, for the rest of the code check out this blog:Customized style mapping system
import tkinter as tk import as ttk from import askopenfilename import matplotlib import matplotlib as mpl ('TkAgg') import .backend_tkagg as mbb from import Figure import numpy as np from alist import AxisList from base import DrawType class DarwSystem(): def __init__(self): = () ("Data presentation tools") = {} = [] () () frmFig = () (side=,fill=,expand=) (frmFig) () def initConst(self): = ("Dotted line diagram.", "Scatterplot.", "Bar graph.") = { "Dotted line diagram." : , "Scatterplot." : , "Bar graph." : } # ! Setting def setFrmCtrl(self): frmCtrl = (,width=320) (side=, fill=) # Master Frame frm = (frmCtrl, width=320) (side=, fill=) (frm) # Animation control frm = (frmCtrl, width=320) (side=, fill=) (frm) = (frmCtrl) (side=, fill=) (None) # ! toolbar (in computer software) def setCtrlButtons(self, frm): = DrawType(frm) (side=) (frm, text="📈",width=3, command=).pack(side=) (frm, text="📂",width=3, command=).pack(side=) btn = (frm, text="+", width=3) (side=) ("<Button-1>", ) btn = (frm, text="-", width=3) (side=) ("<Button-1>", ) # ! Animation Controls def setAnimateFrame(self, frm): pDct = dict(side=, fill=, padx=2) = () (100) (frm, text="Delay/milliseconds").pack(**pDct) (frm, width=5, textvariable=).pack(**pDct) = () (100) (frm, text="Frames.").pack(**pDct) (frm, width=5, textvariable=).pack(**pDct) = 0 # Current frames (frm, width=3, text= "⇦", command=).pack(**pDct) (frm, width=3, text="▶", command=).pack(**pDct) (frm, width=3, text="⇨", command=).pack(**pDct) def btnAniStart(self): pass def btnPreFrame(self): pass def btnNextFrame(self): num = () = ( + 1) % num () # Add a set of coordinate systems def addLast(self, evt): title = f"coordinate (geometry){len()}" al = AxisList(, title, 1, [5,10,30], , ()) (side=, fill=) (al) # Delete a set of coordinate systems def deleteLast(self, evt): [-1].pack_forget() del [-1] # Load data // Temporarily in the discarded state def btnLoadData(self): name = askopenfilename() data = (name) for i, flag in enumerate('xyz'): if i >= [1]: return (flag, "External import") [flag] = (flag, data = data[:,i]) # Read the data from the axes al def readDatas(self, al): dct = {} data = {} for flag in (): data[flag] = (flag, **dct) if flag=='t': dct['t'] = data['t'][] else: dct[flag] = data[flag] return data # Set the plotting coordinates def setDrawAxis(self, al): sub = int(()) print(sub) if sub in : return [sub] p = () if p == "None": [sub] = .add_subplot(sub) else: [sub] = .add_subplot(sub, projection=p) return [sub] # Single-frame plotting functions def btnDrawImg(self): () = {} for al in : ax = (al) data = (al) draw = [()] style = () keys = ().replace('t',"") draw(ax, data, keys, style) .subplots_adjust(left=0.1, right=0.95, top=0.95, bottom=0.08) () def drawBar(self, ax, data, keys, style): (data['x'], data['y']) def drawPlot(self, ax, data, keys, style): (*[data[key] for key in keys], **style) def drawScatter(self, ax, data, keys, style): (*[data[key] for key in keys]) def setFrmFig(self, frmFig): = Figure() = (,frmFig) .get_tk_widget().pack( side=,fill=,expand=) = mbb.NavigationToolbar2Tk(,frmFig, pack_toolbar=False) () (side=) if __name__ == "__main__": test = DarwSystem()
Above is Python add timeline to achieve dynamic drawing details, more information about Python dynamic drawing, please pay attention to my other related articles!