当前位置:首页 > 编程笔记 > 正文
已解决

绘图系统四:定制绘图风格

来自网友在路上 152852提问 提问时间:2023-09-21 10:10:54阅读次数: 52

最佳答案 问答题库528位专家为你答疑解惑

文章目录

    • 创建控件
    • 绘图风格
    • 可定制绘图风格的绘图系统
    • 代码组织

  • 📈一 三维绘图系统 📈二 多图绘制系统
  • 📈三 坐标轴定制
  • 源码地址 Python打造动态绘图系统

创建控件

尽管从matplotlib的角度来说,绘图风格也算是图像类型的一部分,但诸如点线字体标题等内容太过复杂,为了减轻DrawType的负担,所以新建一个组件。有了DrawType的经验,那么DrawStyle类在参数设置上就比较轻车熟路,整体框架大致如下

class DrawStyle(ttk.Frame):def __init__(self, master, varDct, ws=None, func=None, **options):super().__init__(master, **options)self.pack()def initVars(self):passdef initWidgets(self):pass

但在丰富细节之前,需要修改一下AxisList的布局。考虑到绘图风格并不是经常会用到的控件,所以平时给隐藏起来。其initWidgets函数修改如下,之前直接依托在主frame中的AxisFrame,如今都要放到self._a中。而各种按钮都放在工具栏self._b中。

def initWidgets(self, title, widths):self.btn = ttk.Button(self, text=title, width=sum(widths)+5,command=self.Click)self.btn.pack(side=tk.TOP, fill=tk.X, expand=tk.YES)self._c = ttk.Frame(self)       # 此为主frameself._b = ttk.Frame(self._c)    # 此外工具栏控件self._a = ttk.Frame(self._c)    # 此为坐标轴self._s = ttk.Frame(self._c)    # 此为绘图风格控件self._b.pack(side=tk.TOP)self._a.pack(side=tk.TOP)self._s.pack(side=tk.TOP)self.collapsed = Trueself.Click()

然后添加风格按钮

def initFeature(self, types, typeDct):frm = self._b# ...中间内容不变ttk.Button(frm, text="风格",width=5,command=self.btnShowStyle).pack(side=tk.LEFT)self.showStyle = False

btnShowStyle的逻辑也是老生常谈了

def btnShowStyle(self):self.showStyle = not self.showStyleif self.showStyle:self.sf.pack(side=tk.TOP, fill=tk.X)else:self.sf.pack_forget()

风格初始化如下

def initStyleFrame(self):self.sf = DrawStyle(self._s)ttk.Button(self.sf, text="点我").pack(side=tk.LEFT)

这个按钮存粹为了演示,后期要删掉的,演示结果如下

在这里插入图片描述

绘图风格

以plot为例,下面列出常用参数,其中枚举类型表示有有限个可选择的值,说明适用于Combobox控件。

参数类型功能参数类型功能label字符串图例标签linestyle枚举线条类型linewidth小数线条宽度marker枚举散点形状markersize小数散点尺寸alpha小数透明度zorder整数所在绘图层color字符串颜色markeredgecolor字符串点的边框色

为了便于调用,将这些参数封装为字典

def initConst(self):self.VAR_LABS = {"线型" : "linestyle", "线宽" : "linewidth",  "线色" : "color","点型" : "marker"   , "点径" : "markersize", "点色" : "markeredgecolor","标签" : "label"    , "透明度"    : "alpha", "层号" : "zorder" }self.STR_KEYS = ["标签"]self.COM_KEYS = ["线型", "点型"]self.NUM_KEYS = ["线宽", "点径", "透明度"]self.INT_KEYS = ["层号"]self.CLR_KEYS = ["线色", "点色"]

这样一来,初始化StringVar就方便很多

def initVars(self):self.varDct = {key:tk.StringVar() for key in self.VAR_LABS}

但接下来才是重头戏,UI绘制。

matplotlib中有四种线型,点型相对较多,而点和线的设置均包含形状、尺寸以及颜色,基于这种对偶关系,可以将这些参数设成下列形式

def initLineMarker(self):enumDct = {"点型" : ['.', ',', '1', '2', '3', '4', '+', 'x', '|', '_', 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 'o', 'v', '^', '<', '>', '8', 's', 'p', '*', 'h', 'H', 'D', 'd', 'P', 'X'],"线型" : ['-', '--', '-.', ':']}frm = self.newFrame()for i in range(2):key = self.COM_KEYS[i]ttk.Label(frm, text=key).grid(row=i, column=0, padx=2)tmp = ttk.Combobox(frm, width=10, textvariable=self.varDct[key])tmp.grid(row=i, column=1, padx=2, pady=2)tmp['value'] = enumDct[key]key = self.NUM_KEYS[i]ttk.Label(frm, text=key).grid(row=i, column=2, padx=2)tmp = ttk.Entry(frm, width=10, textvariable=self.varDct[key])tmp.grid(row=i, column=3, padx=2, pady=2)key = self.CLR_KEYS[i]ttk.Label(frm, text=key).grid(row=i, column=4, padx=2)tmp = ttk.Entry(frm, width=10, textvariable=self.varDct[key])tmp.grid(row=i, column=5, padx=2, pady=2)

在这里插入图片描述

这样一来就只剩下标签,层号和透明度这三个参数了,由于标签颇有标题的意味,所以把这三个参数放在线型上面。

最后得到

在这里插入图片描述

可定制绘图风格的绘图系统

如果想在DrawSystem中调用绘图风格,那么就需要DrawStyle对象可以输出绘图参数,由于这里面所有的参数都在字典里面,所以这一步非常容易

def getOneVar(self, key):v = self.varDct[key].get()if v=="": return ""if key in NUM_KEYS: return float(v)elif key in INT_KEYS: return int(v)else: return vdef getVarDct(self):dct = {self.VAR_LABS[key] : self.varDct[key].get() for key in self.varDct}return {key : dct[key] for key in dct if dct[key]!=""}

第一个函数用于得到某个绘图参数,第二个则用字典的形式,返回所有已经设置的绘图参数。毕竟,在plot绘图过程中,并不是需要设置所有的绘图参数。

由于DrawStyle是在AxisList中被调用的,所以这个getVarDct函数最好在AxisList中重新封装一下

def getStyle(self):return self.DrawStyle.getVarDct()

最后,绘图风格实现的临门一脚,自然是DrawSystem中的plot函数

def drawPlot(self, ax, data, keys, style):ax.plot(*[data[key] for key in keys], **style)

多了一个style参数,由于绘图函数被重新赋给了func,从而所有绘图函数都要有相同的绘图接口,所以尽管暂时不用,drawScatter和drawBar也要加上style参数。同时更改绘图函数。代码如下,主要添加了一个al.getStyle()的调用。

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

最后得到下面的效果。

在这里插入图片描述

代码组织

目前,这个绘图系统已经有了400多行代码,5个类被放在同一个文件中,修改起来已经有些不便了。为了开发工作得以继续,有必要把这几个类分发到不同的文件中。

在这里插入图片描述

下面新建四个文件,分别放入以下内容

  • base.py:DrawType, DrawStyle
  • aframe.py: AxisFrame
  • alist.py: AxisList
  • ds.py: DrawSystem
查看全文

99%的人还看了

猜你感兴趣

版权申明

本文"绘图系统四:定制绘图风格":http://eshow365.cn/6-10611-0.html 内容来自互联网,请自行判断内容的正确性。如有侵权请联系我们,立即删除!