用Tkinter打造GUI开发工具(49)在Tkinter窗口上动态显示matplotlib.pyplot图形
Posted 荷蒲
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用Tkinter打造GUI开发工具(49)在Tkinter窗口上动态显示matplotlib.pyplot图形相关的知识,希望对你有一定的参考价值。
用Tkinter打造GUI开发工具(49)在Tkinter窗口上动态显示matplotlib.pyplot图形
因为要在Tkinter窗口上动态显示matplotlib.pyplot图形,我首先采用了最先能想到的Tkinter的布局方法。
画图,显示到Tkinter窗口,删除掉绘图,重新画图,并显示到Tkinter窗口。
实现的程序如下。
import random
import numpy as np
import tkinter as tk
from tkinter import *
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import (
FigureCanvasTkAgg, NavigationToolbar2Tk) ##matplotlib 3.0.2
from matplotlib.figure import Figure
#独狼荷蒲qq:2775205
#通通小白python量化群:524949939
#电话微信:18578755056
#通通小白python量化群:524949939
#tkinter,pyqt,gui,Python学习群:647866213
plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
plt.rcParams['axes.unicode_minus']=False #用来正常显示负号
global c,a,root
#----------------------------------------------------------------------
def drawPic():
global c,a,root
"""
获取GUI界面设置的参数,利用该参数绘制图片
"""
#获取GUI界面上的参数
try:
sampleCount=int(inputEntry.get())
r=random.randint(0,1000)
inputEntry.delete(0,END)
inputEntry.insert(0,str(r))
except:
sampleCount=50
print( '请输入整数')
inputEntry.delete(0,END)
inputEntry.insert(0,'50')
#清空图像,以使得前后两次绘制的图像不会重叠
f.clf()
a=f.add_subplot(111)
#在[0,100]范围内随机生成sampleCount个数据点
x=np.random.randint(0,100,size=sampleCount)
y=np.random.randint(0,100,size=sampleCount)
color=['b','r','y','g']
#绘制这些随机点的散点图,颜色随机选取
a.scatter(x,y,s=3,color=color[np.random.randint(len(color))])
a.set_title('画图演示')
plt.show()
def drawPic2():
global c,a,root
"""
获取GUI界面设置的参数,利用该参数绘制图片
"""
#获取GUI界面上的参数
try:
sampleCount=int(inputEntry.get())
r=random.randint(0,1000)
inputEntry.delete(0,END)
inputEntry.insert(0,str(r))
except:
sampleCount=50
print( '请输入整数')
inputEntry.delete(0,END)
inputEntry.insert(0,'50')
#清空图像,以使得前后两次绘制的图像不会重叠
f.clf()
a=f.add_subplot(111)
#在[0,100]范围内随机生成sampleCount个数据点
x=np.random.randint(0,100,size=sampleCount)
y=np.random.randint(0,100,size=sampleCount)
color=['b','r','y','g']
#绘制这些随机点的散点图,颜色随机选取
a.scatter(x,y,s=3,color=color[np.random.randint(len(color))])
a.set_title('画图演示 %d'%sampleCount)
c.grid_forget()
c=Canvas(root)
c.grid(row=0, columnspan=3)
canvas = FigureCanvasTkAgg(f, master=c)
canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1)
#canvas.show()
if __name__ == '__main__':
global c,a,root
root=Tk()
#放置标签、文本框和按钮等部件,并设置文本框的默认值和按钮的事件函数
Label(root,text='请输入样本数量:').grid(row=1,column=0)
inputEntry=Entry(root)
inputEntry.grid(row=1,column=1)
inputEntry.insert(0,'50')
c=Canvas(root)
c.grid(row=0, columnspan=3)
#在Tk的GUI上放置一个画布,并用.grid()来调整布局
f = plt.Figure(figsize=(5,4), dpi=100)
drawPic()
canvas = FigureCanvasTkAgg(f, master=c)
canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1)
Button(root,text='画图',command=drawPic2).grid(row=1,column=2,columnspan=3)
#启动事件循环
root.mainloop()
程序运行结果如下图。
我们可以看到,快速更换图形,会引起画面的闪烁。这样的话,对用户体验不好。
这个需要如何解决问题呢?
我们可以使用matplotlib.animation的模块,来动态显示图形。
在matplotlib作图中,用的是matplotlib.pyplot模块,这个模块有非常多的属性和方法,简要列举下这次用到的方法:
matplotlib.pyplot.subplots(nrows=1, ncols=1, sharex=False, sharey=False, squeeze=True, subplot_kw=None, gridspec_kw=None, **fig_kw)
返回fig和ax对象!
下面我们直接给出示例代码,供读者参考。
# -*- coding: utf-8 -*-
import random
import numpy as np
import tkinter as tk
from tkinter import *
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import (
FigureCanvasTkAgg, NavigationToolbar2Tk) ##matplotlib 3.0.2
from matplotlib.figure import Figure
#独狼荷蒲qq:2775205
#通通小白python量化群:524949939
#电话微信:18578755056
#通通小白python量化群:524949939
#tkinter,pyqt,gui,Python学习群:647866213
plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
plt.rcParams['axes.unicode_minus']=False #用来正常显示负号
global c,a,root
#----------------------------------------------------------------------
def drawPic():
global c,a,root
"""
获取GUI界面设置的参数,利用该参数绘制图片
"""
#获取GUI界面上的参数
try:
sampleCount=int(inputEntry.get())
r=random.randint(0,1000)
inputEntry.delete(0,END)
inputEntry.insert(0,str(r))
except:
sampleCount=50
print( '请输入整数')
inputEntry.delete(0,END)
inputEntry.insert(0,'50')
#清空图像,以使得前后两次绘制的图像不会重叠
f.clf()
a=f.add_subplot(111)
#在[0,100]范围内随机生成sampleCount个数据点
x=np.random.randint(0,100,size=sampleCount)
y=np.random.randint(0,100,size=sampleCount)
color=['b','r','y','g']
#绘制这些随机点的散点图,颜色随机选取
a.scatter(x,y,s=3,color=color[np.random.randint(len(color))])
a.set_title('画图演示')
plt.show()
def drawPic2():
global c,a,root
"""
获取GUI界面设置的参数,利用该参数绘制图片
"""
#获取GUI界面上的参数
try:
sampleCount=int(inputEntry.get())
r=random.randint(0,1000)
inputEntry.delete(0,END)
inputEntry.insert(0,str(r))
except:
sampleCount=50
print( '请输入整数')
inputEntry.delete(0,END)
inputEntry.insert(0,'50')
#清空图像,以使得前后两次绘制的图像不会重叠
f.clf()
#在[0,100]范围内随机生成sampleCount个数据点
x=np.random.randint(0,100,size=sampleCount)
y=np.random.randint(0,100,size=sampleCount)
color=['b','r','y','g']
#绘制这些随机点的散点图,颜色随机选取
a.scatter(x,y,s=3,color=color[np.random.randint(len(color))])
a.set_title('画图演示 %d'%sampleCount)
canvas = FigureCanvasTkAgg(f, master=c)
c.update()
import matplotlib.animation as animation
def plt01():
f = plt.figure(figsize=(6, 6))
ax = plt.gca()
ax.grid()
ln1, = ax.plot([], [], '-', lw=2)
ln2, = ax.plot([], [], '-', color='r', lw=2)
theta = np.linspace(0, 2*np.pi, 100)
r_out = 1
r_in = 0.5
time_template = 'time = %.1fs'
time_text = ax.text(0.05, 0.9, '', transform=ax.transAxes)
def init():
ax.set_xlim(-2, 2)
ax.set_ylim(-2, 2)
x_out = [r_out*np.cos(theta[i]) for i in range(len(theta))]
y_out = [r_out*np.sin(theta[i]) for i in range(len(theta))]
ln1.set_data(x_out, y_out)
return ln1,
def update(i):
x_in = [(r_out-r_in)*np.cos(theta[i])+r_in*np.cos(theta[j]) for j in range(len(theta))]
y_in = [(r_out-r_in)*np.sin(theta[i])+r_in*np.sin(theta[j]) for j in range(len(theta))]
ln2.set_data(x_in, y_in)
time_text.set_text(time_template %(0.1*i))
return ln2,
c=Canvas(root)
c.grid(row=0, columnspan=3)
canvas = FigureCanvasTkAgg(f, master=c)
canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1)
ani = animation.FuncAnimation(f, update, range(len(theta)), init_func=init, interval=10)
#ani.save('ls.gif', writer='imagemagick', fps=100)
plt.show()
plt.close() # 关窗口
if __name__ == '__main__':
global c,a,root
#matplotlib.use('TkAgg')
root=Tk()
plt01()
#启动事件循环
root.mainloop()
下面是程序运行的结果。
我们可以看到,现在窗口和图形不再闪烁了。一些朋友说直接用plt窗口就可以直接显示动态图形了,没必要套在一起使用。
我们这样使用是为了第三代小白量化软件的设计,第三代图将实现实时数据K线或 分时图,需要比较连贯的图形显示方法,下来我们就用这个技术尝试一下。
下面是我们第三代小白量化软件的截图,还没有开发完成。
可以通过下面方式与我交流:
#独狼荷蒲qq:2775205
#通通小白python量化群:524949939
#电话微信:18578755056
#通通小白python量化群:524949939
#tkinter,pyqt,gui,Python学习群:647866213
欢迎继续关注我的博客。
超越自己是我的每一步!我的进步就是你的进步!
以上是关于用Tkinter打造GUI开发工具(49)在Tkinter窗口上动态显示matplotlib.pyplot图形的主要内容,如果未能解决你的问题,请参考以下文章
用Tkinter打造自己的Python IDE开发工具利用HP_tk模块设计自己的代码编辑器
用Tkinter打造自己的Python IDE开发工具利用HP_tk模块设计自己的代码编辑器
用Tkinter打造自己的Python IDE开发工具利用HP_tk模块设计自己的代码编辑器