绘图系统四:定制绘图风格
最佳答案 问答题库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控件。
为了便于调用,将这些参数封装为字典
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 内容来自互联网,请自行判断内容的正确性。如有侵权请联系我们,立即删除!
- 上一篇: redux使用,相当于vue中的vuex
- 下一篇: SAP 打note步骤