文章目录
- 动图绘制系统的实现
- 播放控制
- 接口优化
- 总结
Python绘图系统:
- 源码地址:Python打造动态绘图系统
- 📈从0开始的3D绘图系统📉一套3D坐标,多个函数📊散点图、极坐标和子图
- 自定义控件:绘图风格📉风格控件📊定制绘图风格
- 坐标设置进阶:动态更新组件📌导入外部文件📌导入txt
- 动图绘制:动图绘制
动图绘制系统的实现
所谓动图绘制,其实只需要一个循环,并且每次绘图之前,要有一定的延时。启用多线程和延时,需要导入下面两个模块
from threading import Thread
import time
接下来,就是self.btnAniStart函数和具体的动图绘制函数了
def btnAniStart(self):
Thread(target=self.btnDrawCycle, daemon=True).start()
def btnDrawCycle(self):
dt = self.aniDelay.get()/1000.0
for i in range(self.aniFrameNum.get()):
self.tIndex = i
self.btnDrawImg()
time.sleep(dt)
点击播放按钮后效果如下
播放控制
从图像播放的角度来说,这个设计并不十分合理,因为点击播放的三角号之后,应该要给出一个停止播放的按钮,相应地DrawCycle函数也应该新增一个无尽循环模式。
为了实现播放控制,为播放按钮绑定一个可变字符串
self.btnStartText = tk.StringVar()
self.btnStartText.set("▶")
ttk.Button(frm, width=3, textvariable=self.btnStartText,
command=self.btnAniStart).pack(**pDct)
然后修改btnAniStart,大致改成下面的形式,但这里只是添加了暂停的逻辑,但并没有真正实现暂停的功能
def btnAniStart(self):
if self.btnStartText.get() == "▶":
Thread(target=self.drawCycle, daemon=True).start()
self.btnStartText.set("⏸")
else:
self.btnStartText.set("▶")
而真正实现暂停功能,就需要修改drawCycle函数了
def drawCycle(self):
dt = self.aniDelay.get()/1000.0
num = self.aniFrameNum.get()
while self.btnStartText.get() == "⏸":
self.tIndex = (self.tIndex + 1) % num
self.btnDrawImg()
time.sleep(dt)
至此,就完成了一个动态图像绘制系统。
接口优化
开发过程中会经常遇到新增的需求,这些需求的实现,会对原来的设计形成干扰,而且这些需求累加在一起,会导致代码变得十分畸形。比如一开始DrawType类只包含绘图类型和维度,所以在AxisList中做对象的时候,变量名取为drawTypeDim。但后来DrawType又加入了其他功能,使得drawTypeDim这个变量变得很蠢,所以接下来要重新命名。
主要变更如下
-
AxisList类
- drawTypeDim 变为 drawType
-
DrawSystem类
- drawTypeDim 变为 drawType
-
AxisList类中定义的函数,但DrawSystem中有调用
- getDrawType -> getType
- getDrawDim -> getDim
另外,由于t轴和xyz在绘图时的作用相去甚远,所以将getDim函数拆分成xyz和t两个函数。在AxisList中新增两个函数
def getXYZ(self):
return self.getDim().replace("t", "")
def hasTimeAxis(self):
return "t" in self.getDim()
更改DrawSystem中的调用,btnDrawImg
中al.getDim().replace('t',"")
改为al.getXYZ()
;readDatas
改写如下
def readDatas(self, al):
dct = {}
data = {}
if al.hasTimeAxis():
data['t'] = al.setData('t')
dct['t'] = data['t'][self.tIndex]
for flag in al.getXYZ():
data[flag] = al.setData(flag, **dct)
dct[flag] = data[flag]
return data
总结
本文正好是Python绘图系统的第20篇博客。目前,这个绘图系统可以绘制二维Plot,三维Plot,极坐标Plot,而且支持子图的绘制。而今又添加了动态图形的绘制功能。
尽管从目前来说,这段程序称不上是一个完备的软件,因为这里没有基本的报错系统,也没有日志管理系统,但作为一个快速入门的基础项目来说,却是非常适宜的。同时,这个系统已经具备了初步的骨架,基于这套代码,可以进一步实现更加复杂的绘图功能,换言之,从极客的角度来说,这个绘图系统已经具备了“可玩性”。
这个项目虽然体量很小,目前只有不到500行代码,但对于一个0到5年码零的Pythoner来说,看了必会有所得。