Python绘图系统:
DrawType类封装了子图位置、坐标轴映射类型以及绘图类型,就基本可以确定绘图坐标以及绘图函数了。
此前,这一步是在DrawSystem中完成的,这显然增加了DrawSystem的负担,若将其挪到DrawType中,显然是更加合理的。甚至于,绘图用的坐标轴和用于绘图的函数,理应成为DrawType的全局变量。
# 如果给定了ax,说明与其他绘图函数公用坐标轴
def setDrawFunc(self, fig, ax=None, **options):
if not ax:
sub = int(self.getSub())
proj = self.getProj() if self.getProj()!="None" else None
ax = fig.add_subplot(sub, projection=p, **options)
self.ax = ax
funcDct = {
"点线图": ax.plot, "曲线图" : ax.plot,
"散点图": ax.scatter,
"图像" : ax.imshow, "伪彩图" : ax.pcolormesh,
"条形图": ax.bar, "横向条形图": ax.barh,
"茎叶图": ax.stem, "阶梯图": ax.step
}
self.draw = funcDct[self.getType()]
return self.draw
前面的逻辑很清晰,如果外部传入了坐标轴,那么就不必再新建一个坐标轴了。后面需要注意funcDct切记不可做成全局变量,而必须建在ax创建之后,因为这里面所调用的所有对象,都是当前坐标轴ax的成员函数。
点线图 | ax.plot | 曲线图 | ax.plot |
散点图 | ax.scatter | ||
图像 | ax.imshow | 伪彩图 | ax.pcolormesh |
条形图 | ax.bar | 横向条形图 | ax.barh |
茎叶图 | ax.stem | 阶梯图 | ax.step |
这个功能在创建之后,需要更改DrawSystem才能验证,并且还涉及到更改AxisList。这里只对DrawSytstem做一个简单的改动,首先添加setDrawFunc函数
def setDrawFunc(self, al):
sub = int(al.getSub())
ax = None if sub not in self.axDct else self.axDct[sub]
ax, draw = al.drawType.setDrawFunc(self.fig, ax)
self.axDct[sub] = ax
return draw
然后更改btnDrawImg函数
def btnDrawImg(self):
self.fig.clf()
self.axDct = {}
for al in self.als:
data = self.readDatas(al)
draw = self.setDrawFunc(al)
style = al.getStyle()
keys = al.getXYZ()
draw(*[data[key] for key in keys], **style)
self.fig.subplots_adjust(left=0.1, right=0.95, top=0.95, bottom=0.08)
self.canvas.draw()
最后效果如下,十分强大
最后附上base.py中的DrawType类的源代码。
# 绘图类型和维度
# varDct 的格式是 {"sub":sub, "type":slctType, "dim":dim, "proj": proj}
class DrawType(ttk.Frame):
# ws为两个combobox的宽
def __init__(self, master,
varDct = {"sub":"111", "type":'点线图', "dim":"xyz", "proj": "3d"},
ws=None, func=None, **options):
super().__init__(master, **options)
self.pack()
self.dimChanged = func
self.initConst()
self.initVar(varDct)
self.initWidgets(ws)
def initVar(self, varDct):
self.drawVars = {key:tk.StringVar() for key in varDct}
for key in self.drawVars:
self.drawVars[key].set(varDct[key])
def initConst(self):
self.TYPES = [
"点线图", "曲线图", "散点图", "图像", "伪彩图",
"条形图", "横向条形图", "茎叶图", "阶梯图"]
def initWidgets(self, ws):
if ws==None: ws = [5, 5, 5, 3]
slctDct = {'type': self.TYPES,
'proj': ("None", "3d", "polar"),
'dim' : ("x", "xy", "xyz")} # 绘图维度
keys = ['sub', 'type', 'proj', 'dim']
self.wDct = {} # 控件字典
# 此为设置子图的Entry控件
self.wDct['sub'] = ttk.Entry(self, width=ws[0],
textvariable=self.drawVars['sub'])
for i, key in enumerate(keys[1:], 1):
self.wDct[key] = ttk.Combobox(self, width=ws[i],
textvariable=self.drawVars[key])
self.wDct[key]['value'] = slctDct[key]
for key in keys:
self.wDct[key].pack(side=tk.LEFT, padx=2)
self.wDct['type'].bind('<>' , self.cbTypeChanged)
self.wDct['proj'].bind('<>' , self.cbProjChanged)
self.wDct['dim'].bind('<>' , self.dimChanged)
def cbTypeChanged(self, evt):
t = self.drawVars['type'].get()
p = self.drawVars['proj'].get()
if t in ("图像"):
self.wDct['proj']['value'] = ("None")
elif t in ("横向条形图", "伪彩图"):
self.wDct['proj']['value'] = ("None", "polar")
else:
self.wDct['proj']['value'] = ("None", "3d", "polar")
projs = self.wDct['proj']['value']
if p not in projs:
self.drawVars['proj'].set(projs[0])
self.cbProjChanged(None)
def cbProjChanged(self, evt):
p = self.drawVars['proj'].get()
func = {
'None': self.cbProjNone,
'3d': self.cbProj3d,
'polar' : self.cbProjPolar}
d = self.wDct['dim'].get()
t = self.drawVars['type'].get()
func[p](t)
dims = self.wDct['dim']['value']
if d not in dims:
self.drawVars['dim'].set(dims[0])
self.dimChanged(None)
def cbProjNone(self, t):
if t in ("点线图", "曲线图"):
self.wDct['dim']['value'] = ('x', 'xy')
elif t in ("图像"):
self.wDct['dim']['value'] = ('x')
elif t in ("伪彩图"):
self.wDct['dim']['value'] = ('x', 'xyz')
else:
self.wDct['dim']['value'] = ('xy')
def cbProjPolar(self, t):
if t in ("点线图", "曲线图"):
self.wDct['dim']['value'] = ('x', 'xy')
elif t in ("伪彩图"):
self.wDct['dim']['value'] = ('xyz')
else:
self.wDct['dim']['value'] = ('xy')
def cbProj3d(self, t):
self.wDct['dim']['value'] = ('xy', 'xyz')
# 如果给定了ax,说明与其他绘图函数公用坐标轴
def setDrawFunc(self, fig, ax=None, **options):
if not ax:
sub = int(self.getSub())
p = self.getProj() if self.getProj()!="None" else None
ax = fig.add_subplot(sub, projection=p, **options)
self.ax = ax
funcDct = {
"点线图": ax.plot, "曲线图" : ax.plot,
"散点图": ax.scatter,
"图像" : ax.imshow, "伪彩图" : ax.pcolormesh,
"条形图": ax.bar, "横向条形图": ax.barh,
"茎叶图": ax.stem, "阶梯图": ax.step
}
self.draw = funcDct[self.getType()]
return self.ax, self.draw
def setFunc(self):
self.ax
def getSub(self):
return self.drawVars['sub'].get()
def getType(self):
return self.drawVars['type'].get()
def getDim(self):
return self.drawVars['dim'].get()
def getProj(self):
return self.drawVars['proj'].get()
def getDct(self):
return {key:self.drawVars[key].get() for key in self.drawVars}