• Python实现四维图像绘制系统


    Python绘图系统:

    动图绘制系统的实现

    所谓动图绘制,其实只需要一个循环,并且每次绘图之前,要有一定的延时。启用多线程和延时,需要导入下面两个模块

    from threading import Thread
    import time
    
    • 1
    • 2

    接下来,就是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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    点击播放按钮后效果如下

    在这里插入图片描述

    播放控制

    从图像播放的角度来说,这个设计并不十分合理,因为点击播放的三角号之后,应该要给出一个停止播放的按钮,相应地DrawCycle函数也应该新增一个无尽循环模式。

    为了实现播放控制,为播放按钮绑定一个可变字符串

    self.btnStartText = tk.StringVar()
    self.btnStartText.set("▶")
    ttk.Button(frm, width=3, textvariable=self.btnStartText,
        command=self.btnAniStart).pack(**pDct)
    
    • 1
    • 2
    • 3
    • 4

    然后修改btnAniStart,大致改成下面的形式,但这里只是添加了暂停的逻辑,但并没有真正实现暂停的功能

    def btnAniStart(self):
        if self.btnStartText.get() == "▶":
            Thread(target=self.drawCycle, daemon=True).start()
            self.btnStartText.set("⏸")
        else:
            self.btnStartText.set("▶")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    而真正实现暂停功能,就需要修改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)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述

    至此,就完成了一个动态图像绘制系统。

    接口优化

    开发过程中会经常遇到新增的需求,这些需求的实现,会对原来的设计形成干扰,而且这些需求累加在一起,会导致代码变得十分畸形。比如一开始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()
    
    • 1
    • 2
    • 3
    • 4
    • 5

    更改DrawSystem中的调用,btnDrawImgal.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
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    总结

    本文正好是Python绘图系统的第20篇博客。目前,这个绘图系统可以绘制二维Plot,三维Plot,极坐标Plot,而且支持子图的绘制。而今又添加了动态图形的绘制功能。

    尽管从目前来说,这段程序称不上是一个完备的软件,因为这里没有基本的报错系统,也没有日志管理系统,但作为一个快速入门的基础项目来说,却是非常适宜的。同时,这个系统已经具备了初步的骨架,基于这套代码,可以进一步实现更加复杂的绘图功能,换言之,从极客的角度来说,这个绘图系统已经具备了“可玩性”。

    这个项目虽然体量很小,目前只有不到500行代码,但对于一个0到5年码零的Pythoner来说,看了必会有所得。

  • 相关阅读:
    Java 8 新特性 Ⅲ
    【软考软件评测师】第十七章 计算机组成与体系结构(总线技术)
    Vit安装配置Ant Design Vue组件库
    线性代数 --- 矩阵的QR分解,A=QR
    在 imx6q 上适配 YT8531S
    分布式运用之Filebeat+Kafka+ELK 的服务部署
    VS Code:CMake配置
    git -- 清除本地分支以及删除远程分支
    将文件移动到ubuntu/linux/centos虚拟机上
    Docker基础入门详解
  • 原文地址:https://blog.csdn.net/m0_37816922/article/details/132169111