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()

實現效果


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM