Tkinter嵌入Matplotlib图表无法更新运行问题求助
串口数据实时图表展示问题
我尝试将Arduino通过串口发送的数据展示在图表上,X轴设为程序启动后的时间,Y轴为串口接收的数据。尝试多种方法后效果不佳,调试无报错但代码疑似在update_graphs()函数中卡住。尝试降低Arduino发送速率无效。
更新1:确定为时序问题——VSCode逐行调试正常,自动运行时程序冻结。
更新2:图表仅在VSCode调试暂停再恢复时更新。
初始Python代码
import tkinter as tk from tkinter import ttk import matplotlib.pyplot as plt from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg import serial import threading import queue import time # 读取串口数据 def read_serial_data(serial_port, data_queue): while True: try: line = serial_port.readline().decode().strip() data_queue.put(line) except UnicodeDecodeError: pass # 更新图表 def update_graphs(): start_time = time.time() global x_data while True: try: data = data_queue.get_nowait() # 计算程序启动后的时间 current_time = time.time() - start_time # 更新数据列表 x_data.append(current_time) # 尝试将数据转为浮点型存入y_data try: y_data.append(float(data)) except ValueError: print(f"数据转浮点型错误: {data}") x_data = x_data[-len(y_data):] # 限制列表长度 ax1.clear() ax1.plot(x_data, y_data, label='传感器数据1') ax1.set_xlabel('时间(秒)') ax1.set_ylabel('传感器数据1') ax1.legend() canvas.draw() except queue.Empty: pass root.after(100, update_graphs) # GUI初始化 root = tk.Tk() root.title("传感器数据图表") # 串口设置 ser = serial.Serial("COM5", baudrate=9600) # 线程间通信队列 data_queue = queue.Queue() # 创建并启动串口读取线程 serial_thread = threading.Thread(target=read_serial_data, args=(ser, data_queue), daemon=True) serial_thread.start() # 创建并启动图表更新线程 update_thread = threading.Thread(target=update_graphs, daemon=True) update_thread.start() # 创建图表 fig, ax1 = plt.subplots() x_data, y_data = [], [] # 存储时间和数据的列表 # 将Matplotlib图表嵌入Tkinter窗口 canvas = FigureCanvasTkAgg(fig, master=root) canvas_widget = canvas.get_tk_widget() canvas_widget.pack(side=tk.TOP, fill=tk.BOTH, expand=1) # 启动Tkinter主循环 root.mainloop()
Arduino代码
void setup() { Serial.begin(9600); } void loop() { Serial.println(random(0, 50)); delay(200); }
更新后的Python代码
import tkinter as tk from tkinter import ttk import matplotlib.pyplot as plt from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg import serial import threading import queue import time # 读取串口数据 def read_serial_data(serial_port, data_queue): while True: try: line = serial_port.readline().decode().strip() data_queue.put(line) except UnicodeDecodeError: pass # 更新图表 def update_graphs(start_time): while True: try: data = data_queue.get(timeout=1) # 计算程序启动后的时间 current_time = time.time() - start_time # 更新数据列表 x_data.append(current_time) y_data.append(float(data)) ax1.clear() ax1.plot(x_data, y_data, label='传感器数据1') ax1.set_xlabel('时间(秒)') ax1.set_ylabel('传感器数据1') ax1.legend() canvas.draw() except queue.Empty: pass except Exception as e: print(f"update_graphs函数错误: {e}") # GUI初始化 root = tk.Tk() root.title("传感器数据图表") # 串口设置 ser = serial.Serial("COM5", baudrate=9600) # 线程间通信队列 data_queue = queue.Queue() # 创建并启动串口读取线程 serial_thread = threading.Thread(target=read_serial_data, args=(ser, data_queue), daemon=True) serial_thread.start() # 创建图表 fig, ax1 = plt.subplots() x_data, y_data = [], [] # 存储时间和数据的列表 # 将Matplotlib图表嵌入Tkinter窗口 canvas = FigureCanvasTkAgg(fig, master=root) canvas_widget = canvas.get_tk_widget() canvas_widget.pack(side=tk.TOP, fill=tk.BOTH, expand=1) # 获取程序启动时间 start_time = time.time() # 每200毫秒调度一次图表更新函数 root.after(200, update_graphs, start_time) # 启动Tkinter主循环 root.mainloop()
内容的提问来源于stack exchange,提问作者HSRibeiro
相关产品推荐
相关产品推荐

