zoukankan      html  css  js  c++  java
  • 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()

    实现效果

  • 相关阅读:
    ThinkingInJava对this关键字的介绍
    MYSQL(三)
    MySQL(二)
    mysql语句实战
    js事件委托
    Python中应该使用%还是format来格式化字符串?
    js高级知识---词法分析和AO 链
    lsof/netstat命令的一个重要作用: 根据进程查端口, 根据端口查进程
    gg
    io多路复用
  • 原文地址:https://www.cnblogs.com/cai-zi/p/15318932.html
Copyright © 2011-2022 走看看