Python tkinter库将matplotlib图表显示在GUI窗口上,并实时更新刷新数据

代码

  1 '''
  2 使用matplotlib创建图表,并显示在tk窗口
  3 '''
  4 import matplotlib.pyplot as plt
  5 from matplotlib.pylab import mpl
  6 from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
  7 import tkinter as tk
  8 import numpy as np
  9 import time,sys
 10 import threading
 11 
 12 mpl.rcParams['font.sans-serif'] = ['SimHei']  # 中文显示
 13 mpl.rcParams['axes.unicode_minus'] = False  # 负号显示
 14 
 15 global win
 16 global tempGraphLabel, tempData, runFlag
 17 runFlag = True
 18 tempData = []
 19 
 20 '''
 21 图表类,定义时参数root为父控件
 22 '''
 23 class tempGraph():
 24     def __init__(self, root):
 25         self.root = root  # 主窗体
 26         self.canvas = tk.Canvas()  # 创建一块显示图形的画布
 27         self.figure = self.create_matplotlib()  # 返回matplotlib所画图形的figure对象
 28         self.showGraphIn(self.figure)  # 将figure显示在tkinter窗体上面
 29 
 30     '''生成fig'''
 31     def create_matplotlib(self):
 32         # 创建绘图对象f
 33         f = plt.figure(num=2, figsize=(16, 8), dpi=100, edgecolor='green', frameon=True)
 34         # 创建一副子图
 35         self.fig11 = plt.subplot(1, 1, 1)
 36         self.line11, = self.fig11.plot([], [])
 37 
 38         def setLabel(fig, title, titleColor="red"):
 39             fig.set_title(title+"温度曲线", color=titleColor)  # 设置标题
 40             fig.set_xlabel('时间[s]')  # 设置x轴标签
 41             fig.set_ylabel("温度[℃]") # 设置y轴标签
 42         setLabel(self.fig11, "设备1")
 43         # fig1.set_yticks([-1, -1 / 2, 0, 1 / 2, 1])  # 设置坐标轴刻度
 44         f.tight_layout() # 自动紧凑布局
 45         return f
 46 
 47     '''把fig显示到tkinter'''
 48     def showGraphIn(self, figure):
 49         # 把绘制的图形显示到tkinter窗口上
 50         self.canvas = FigureCanvasTkAgg(figure, self.root)
 51         self.canvas.draw()  # 以前的版本使用show()方法,matplotlib 2.2之后不再推荐show()用draw代替,但是用show不会报错,会显示警告
 52         self.canvas.get_tk_widget().pack(side=tk.TOP) #, fill=tk.BOTH, expand=1
 53 
 54         # 把matplotlib绘制图形的导航工具栏显示到tkinter窗口上
 55         toolbar = NavigationToolbar2Tk(self.canvas,
 56                                        self.root)  # matplotlib 2.2版本之后推荐使用NavigationToolbar2Tk,若使用NavigationToolbar2TkAgg会警告
 57         toolbar.update()
 58         self.canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1)
 59 
 60     '''更新fig'''
 61     def updateMeltGraph(self, meltData):
 62         x = [i for i in range(len(meltData))]
 63         self.line11.set_xdata(x) # x轴也必须更新
 64         self.line11.set_ydata(meltData)  # 更新y轴数据
 65         #  更新x数据,但未更新绘图范围。当我把新数据放在绘图上时,它完全超出了范围。解决办法是增加:
 66         self.fig11.relim()
 67         self.fig11.autoscale_view()
 68         plt.draw()
 69         # self.canvas.draw_idle()
 70 '''
 71 更新数据,在次线程中运行
 72 '''
 73 def updataData():
 74     global tempData,runFlag
 75     while runFlag:
 76         tempData.append(5)
 77         time.sleep(1)
 78 '''
 79 更新窗口
 80 '''
 81 def updateWindow():
 82     global win
 83     global tempGraphLabel, tempData, runFlag
 84     if runFlag:
 85         tempGraphLabel.updateMeltGraph(tempData)
 86     win.after(1000, updateWindow)  # 1000ms更新画布
 87 '''
 88 关闭窗口触发函数,关闭S7连接,置位flag
 89 '''
 90 def closeWindow():
 91     global runFlag
 92     runFlag = False
 93     sys.exit()
 94 '''
 95 创建控件
 96 '''
 97 def createGUI():
 98     global win
 99     win = tk.Tk()
100     displayWidth = win.winfo_screenwidth()  # 获取屏幕宽度
101     displayHeight = win.winfo_screenheight()
102     winWidth, winHeight = displayWidth, displayHeight - 70
103     winX, winY = -8, 0
104     # winX, winY = int((displayWidth - winWidth) /
105     #                  2), int((displayHeight - winHeight - 70) / 2)
106     win.title("窗口标题")
107     win.geometry(
108         '%dx%d-%d+%d' %
109         (winWidth,
110          winHeight,
111          winX, winY))  # %dx%d宽度x 高度+横向偏移量(距左边)+纵向偏移量(距上边)
112     # win.resizable(0, 0) # 不使能最大化
113     win.protocol("WM_DELETE_WINDOW", closeWindow)
114     # win.iconbitmap(r'resource/images/motor.ico')  # 窗口图标
115 
116     graphFrame = tk.Frame(win) # 创建图表控件
117     graphFrame.place(x=0, y=0)
118     global tempGraphLabel
119     tempGraphLabel = tempGraph(graphFrame)
120 
121     recv_data = threading.Thread(target=updataData)  # 开启线程
122     recv_data.start()
123 
124     updateWindow()  # 更新画布
125     win.mainloop()
126 
127 if __name__ == '__main__':
128     createGUI()

实现效果

posted @ 2021-09-22 10:25  蔡子CaiZi  阅读(5780)  评论(1编辑  收藏  举报