文章目录
- 常用绘图函数
- 单选框的更改逻辑
- 源代码
Python绘图系统:
- 前置源码: Python打造动态绘图系统
- 📈一 三维绘图系统 📈二 多图绘制系统📈三 坐 标 轴 定 制
- 📈四 定制绘图风格 📈五 数据生成导入📈六 三维动态演示
- 动图绘制:动图绘制🔥实现动图绘制系统
- 坐标列表进阶:导出数据📌系统菜单📌批量文件导入📌辅助坐标轴
- 绘图类型进阶:坐标映射📌八种绘图函数
常用绘图函数
目前只集成了三种绘图函数,即plot, scatter和bar,这个体量不到matplotlib提供的绘图函数的十分之一,接下来要做的自然是扩充绘图函数库。
但一次性也不宜扩充太多,下面列出一些常用的绘图函数,如无说明,小写的x,y,z表示一维数组;大写的X,Y,Z表示二维数组,也就是矩阵;❌表示这种绘图函数不支持这种坐标,或者不建议在这种坐标中绘图。
函数 | 类别 | 2D | polar | 3D | 备注 |
---|---|---|---|---|---|
imshow | 图像 | X | ❌ | ❌ | |
pcolormesh | 伪彩图 | [X,Y,]Z | X,Y,Z | ❌ | |
plot | 曲线图 | x[,y] | x[,y] | x,y[,z] | |
scatter | 散点图 | x,y/X,Y | x,y | x,y,[,z] | 可为任意维度 |
stem | 茎叶图 | x,y | x,y | x,y[,z] | |
step | 阶梯图 | x,y | x,y | x,y[,z] | |
bar | 条形图 | x,y | x,y | x,y[,z] | |
barh | 横向条形图 | x,y | x,y | ❌ |
从这个图可以看出,2D坐标中,大部分函数只支持两个变量,极坐标亦然,而3D坐标中要么不支持绘图,要么支持x,y或者x,y,z三种绘图坐标。
单选框的更改逻辑
完成这个功能的改动,只需先更改cbTypeChanged,再更改cbProjNone, cbProjPolar以及cbProj3d这三个函数就可以了。
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)
接下来是设置projection的函数,之前我们一直把plot取名为点线图,这个先留着,但不妨碍把曲线图作为另一个名字加上去,但“点线图”这个名字暂时还不能删,因为DrawSystem那边的代码还没有改。
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')
最后,新建一个全局的常量,用于存储函数名,并在创建slctDct字典时调用。
def initConst(self):
self.TYPES = [
"点线图", "曲线图", "散点图", "图像", "伪彩图",
"条形图", "横向条形图", "茎叶图", "阶梯图"]
修改后的结果如图所示
源代码
下面给出base.py的源代码。
import numpy as np
import tkinter as tk
import tkinter.ttk as ttk
class DrawStyle(ttk.Frame):
def __init__(self, master,
varDct={}, ws=None, func=None, **options):
super().__init__(master, **options)
self.pack()
self.initConst()
self.initVars()
self.initWidgets()
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 = ["线色", "点色"]
def initVars(self):
self.varDct = {key:tk.StringVar() for key in self.VAR_LABS}
def newFrame(self):
frm = ttk.Frame(self)
frm.pack(side=tk.TOP, fill=tk.X)
return frm
def initWidgets(self):
frm = self.newFrame()
for i,key in enumerate(["标签", "层号", "透明度"]):
tk.Label(frm, text=key).grid(row=0, column=i*2, padx=2)
tmp = ttk.Entry(frm, width=10, textvariable=self.varDct[key])
tmp.grid(row=0, column=i*2+1, padx=2, pady=2)
self.initLineMarker(frm)
def initLineMarker(self, frm):
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'],
"线型" : ['-', '--', '-.', ':']
}
for i in range(2):
key = self.COM_KEYS[i]
ttk.Label(frm, text=key).grid(row=i+1, column=0, padx=2)
tmp = ttk.Combobox(frm, width=10, textvariable=self.varDct[key])
tmp.grid(row=i+1, column=1, padx=2, pady=2)
tmp['value'] = enumDct[key]
key = self.NUM_KEYS[i]
ttk.Label(frm, text=key).grid(row=i+1, column=2, padx=2)
tmp = ttk.Entry(frm, width=10, textvariable=self.varDct[key])
tmp.grid(row=i+1, column=3, padx=2, pady=2)
key = self.CLR_KEYS[i]
ttk.Label(frm, text=key).grid(row=i+1, column=4, padx=2)
tmp = ttk.Entry(frm, width=10, textvariable=self.varDct[key])
tmp.grid(row=i+1, column=5, padx=2, pady=2)
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 v
def 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]!=""}
# 绘图类型和维度
# 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('<<ComboboxSelected>>', self.cbTypeChanged)
self.wDct['proj'].bind('<<ComboboxSelected>>', self.cbProjChanged)
self.wDct['dim'].bind('<<ComboboxSelected>>', 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')
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}