3.3.3 在Tkinter中使用Matplotlib绘制图表
在下面的实例文件123.py中,演示了在标准GUI程序Tkinter中使用Matplotlib绘制图表的过程。
源码路径:codes\3\3-3\123.py
class App(tk.Tk):
def __init__(self, parent=None):
tk.Tk.__init__(self, parent)
self.parent = parent
self.initialize()
def initialize(self):
self.title("在Tkinter中使用Matplotlib!")
button = tk.Button(self, text="退出", command=self.on_click)
button.grid(row=1, column=0)
self.mu = tk.DoubleVar()
self.mu.set(5.0) #参数的默认值是"mu"
slider_mu = tk.Scale(self,
from_=7, to=0, resolution=0.1,
label='mu', variable=self.mu,
command=self.on_change
)
slider_mu.grid(row=0, column=0)
self.n = tk.IntVar()
self.n.set(512) #参数的默认值是"n"
slider_n = tk.Scale(self,
from_=512, to=2,
label='n', variable=self.n, command=self.on_change
)
slider_n.grid(row=0, column=1)
fig = Figure(figsize=(6, 4), dpi=96)
ax = fig.add_subplot(111)
x, y = self.data(self.n.get(), self.mu.get())
self.line1, = ax.plot(x, y)
self.graph = FigureCanvasTkAgg(fig, master=self)
canvas = self.graph.get_tk_widget()
canvas.grid(row=0, column=2)
def on_click(self):
self.quit()
def on_change(self, value):
x, y = self.data(self.n.get(), self.mu.get())
self.line1.set_data(x, y) # 更新data数据
# 更新graph
self.graph.draw()
def data(self, n, mu):
lst_y = []
for i in range(n):
lst_y.append(mu * random.random())
return range(n), lst_y
if __name__ == "__main__":
app = App()
app.mainloop()
执行后可以拖动左侧的滑动条控制绘制的图表,执行效果如图3-30所示。
图3-30 执行效果
3.3.4 绘制包含点、曲线、注释和箭头的统计图
请看下面的实例文件jian.py,功能是使用Matplotlib在绘制的曲线中添加注释和箭头。
源码路径:codes\3\3-3\jian.py
import matplotlib.pyplot as plt # 导入绘图模块
import numpy as np # 导入需要生成数据的numpy模块
'''
添加注释 annotate()
参数 :(1)x : 注释文本
(2)xy:
(3) xytext:
(4) 设置箭头,arrowprops
arrowprops : 是一个dict (字典)
第一种方式:{'width':宽度,'headwidth':箭头宽,'headlength':箭头长,
'shrink':两端收缩总长度分数}
例如:arrowprops={'width':5,'headwidth':10,'headlength':10,'shrink':0.1}
第二种方式:'arrowstyle':样式
例如:
有关arrowstyle的样式:'-' 、'->'、'<-'、'-['、'|-|'、'-|>'、'<|-'、'<->'
'fancy','simple','wedge'
'''
x = np.random.randint(0,30,size=10)
x[5] = 30 # 把索引为5的位置改为30
plt.figure(figsize=(12,6))
plt.plot(x)
plt.ylim([-2,35]) # 设置y轴的刻度
plt.annotate(s='this point is important',xy=(5,30),xytext=(7,31),
arrowprops={'arrowstyle':'->'})
plt.show()
执行效果如图3-31所示。
图3-31 执行效果
再看下面的实例文件zong.py,功能是使用Matplotlib绘制包含点、曲线、注释和箭头的统计图。
源码路径:codes\3\3-3\zong.py
from matplotlib import pyplot as plt
import numpy as np
# 绘制曲线
x = np.linspace(2, 21, 20) # 取闭区间[2, 21]之间的等差数列,列表长度20
y = np.log10(x) + 0.5
plt.figure() # 添加一个窗口。如果只显示一个窗口,可以省略该句。
plt.plot(x, y) # plot在一个figure窗口中添加一个图,绘制曲线,默认颜色
# 绘制离散点
plt.plot(x, y, '.y') # 绘制黄色的点,为了和曲线颜色不一样
x0, y0 = 15, np.log10(15) + 0.5
plt.annotate('Interpolation point', xy=(x0, y0), xytext=(x0, y0 - 1), arrowprops=dict(arrowstyle='->')) # 添加注释
for x0, y0 in zip(x, y):
plt.quiver(x0, y0 - 0.3, 0, 1, color='g', width=0.005) # 绘制箭头
x = range(2, 21, 5)
y = np.log10(x) + 0.5
plt.plot(x, y, 'om') # 绘制紫红色的圆形的点
x0, y0 = 7, np.log10(7) + 0.5
plt.annotate('Original point', xy=(x0, y0), xytext=(x0, y0 - 1), arrowprops=dict(arrowstyle='->'))
for x0, y0 in zip(x, y):
plt.quiver(x0, y0 + 0.3, 0, -1, color='g', width=0.005) # 绘制箭头
# 设置坐标范围
plt.xlim(2, 21) # 设置x轴范围
plt.xticks(range(0, 23, 2)) # 设置X轴坐标点的值,为[0, 22]之间的以2为差值的等差数组
plt.ylim(0, 3) # 设置y轴范围
# 显示图形
plt.show() # 显示绘制出的图
对上述代码的具体说明如下:
(1)导入matplotlib模块的pyplot类,这里主要用了pyplot里的一些方法。导入numpy用于生成一些数列,分别给pyplot和numpy记个简洁的别名plt和n,。
(2)通过方法np.linspace(start, stop, num)生成闭区间[stop, stop]里的数组长度为num的等差数列,在本例中想作为插值点显示出来。
(3)通过方法plt.figure()添加窗口。如果把所有图形绘制在一个窗口里则可以省略该行代码,因为figure(1)会被默认创建。如果想添加窗口,则需要再添加一行代码plt.figure(),plt.figure(num)的窗口序号num会自动自增加1。
(4)通过方法plt.plot()在窗口中绘制曲线,传递x, y参数,分别表示横轴和纵轴。
本实例的执行效果如图3-32所示。
图3-32 执行效果
3.3.5 在两栋房子之间绘制箭头指示符
请看下面的实例文件zhishi.py,首先使用散点图表示房子的位置,然后在两栋房子之间绘制箭头指示符。
源码路径:codes\3\3-3\zhishi.py
import numpy as np
import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(5, 5))
ax.set_aspect(1)
x1 = -1 + np.random.randn(100)
y1 = -1 + np.random.randn(100)
x2 = 1. + np.random.randn(100)
y2 = 1. + np.random.randn(100)
ax.scatter(x1, y1, color="r")
ax.scatter(x2, y2, color="g")
bbox_props = dict(boxstyle="round", fc="w", ec="0.5", alpha=0.9)
ax.text(-2, -2, "住宅A", ha="center", va="center", size=20,
bbox=bbox_props, fontproperties="SimSun")
ax.text(2, 2, "住宅B", ha="center", va="center", size=20,
bbox=bbox_props,fontproperties="SimSun")
bbox_props = dict(boxstyle="rarrow", fc=(0.8, 0.9, 0.9), ec="b", lw=2)
t = ax.text(0, 0, "Direction", ha="center", va="center", rotation=45,
size=15,
bbox=bbox_props)
bb = t.get_bbox_patch()
bb.set_boxstyle("rarrow", pad=0.6)
ax.set_xlim(-4, 4)
ax.set_ylim(-4, 4)
plt.show()
本实例的执行效果如图3-33所示。
图3-33 执行效果