You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PyQt5主界面嵌入Matplotlib图表及树莓派串口数据绘图求助

Solution: Embed Matplotlib in PyQt5 & Serial Data Plotting for Raspberry Pi

Got it, let's tackle your two main needs: embedding Matplotlib charts directly into your PyQt5 main window (instead of popping up separate windows) and setting up real-time plotting from serial data on your Raspberry Pi. Here's a step-by-step fix with updated code:

1. Fixing Matplotlib Embedding in PyQt5

Your current code uses global plt functions that spawn standalone windows. To embed the chart into your main UI, we'll use Matplotlib's Qt-compatible canvas component.

First, add these required imports:

import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure

Then update your ApplicationWindow class. Note: You'll need to add a QWidget (or QFrame) to your Qt Designer UI (name it widget_graph) to act as the chart container.

class ApplicationWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super(ApplicationWindow, self).__init__()
        self.ui = Ui_Form()
        self.ui.setupUi(self)
        
        # Initialize Matplotlib figure and canvas
        self.figure = Figure(figsize=(5, 4), dpi=100)
        self.canvas = FigureCanvas(self.figure)
        
        # Attach canvas to your UI's widget container
        layout = QtWidgets.QVBoxLayout(self.ui.widget_graph)
        layout.addWidget(self.canvas)
        
        # Connect button to data load function
        self.ui.pushButtonGraph.clicked.connect(self.load_Data)

    def load_Data(self):
        # Clear previous plot for clean updates
        self.figure.clear()
        
        # Create an axes object from the figure
        ax = self.figure.add_subplot(111)
        
        # Your sample data
        x = [2, 4, 6, 8, 10]
        y = [6, 7, 8, 2, 10]
        
        # Plot on the embedded axes
        ax.bar(x, y, label='Bar 1')
        ax.set_xlabel('x')
        ax.set_ylabel('y')
        ax.set_title('Graph test')
        ax.legend()
        
        # Refresh the canvas to show the new plot
        self.canvas.draw()

This replaces the standalone plt.show() with a canvas that's directly integrated into your main interface.

2. Adding Serial Data Plotting for Raspberry Pi

To read serial data without freezing your PyQt5 UI, we'll use a QThread (separate thread for serial reading) to avoid blocking the main UI thread.

First, install pyserial if you haven't:

pip install pyserial

Add these additional imports:

import serial
from PyQt5.QtCore import QThread, pyqtSignal

Then add a serial thread class and update your main window for real-time plotting:

class SerialThread(QThread):
    # Signal to send parsed data back to the main thread
    data_received = pyqtSignal(float)

    def __init__(self, port='/dev/ttyUSB0', baud_rate=9600):
        super().__init__()
        self.port = port
        self.baud_rate = baud_rate
        self.running = True

    def run(self):
        # Open serial port (adjust port for your Raspberry Pi setup)
        try:
            ser = serial.Serial(self.port, self.baud_rate, timeout=1)
            while self.running:
                # Read and parse serial data (adjust parsing logic as needed)
                line = ser.readline().decode('utf-8').strip()
                if line:
                    try:
                        data = float(line)
                        self.data_received.emit(data)
                    except ValueError:
                        print(f"Invalid data received: {line}")
            ser.close()
        except serial.SerialException as e:
            print(f"Serial connection error: {e}")

    def stop(self):
        self.running = False

# Updated ApplicationWindow with serial plotting support
class ApplicationWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super(ApplicationWindow, self).__init__()
        self.ui = Ui_Form()
        self.ui.setupUi(self)
        
        # Initialize Matplotlib components for real-time plotting
        self.figure = Figure(figsize=(5, 4), dpi=100)
        self.canvas = FigureCanvas(self.figure)
        self.ax = self.figure.add_subplot(111)
        self.ax.set_xlabel('Time')
        self.ax.set_ylabel('Serial Data')
        self.ax.set_title('Real-Time Serial Plot')
        
        # Attach canvas to UI container
        layout = QtWidgets.QVBoxLayout(self.ui.widget_graph)
        layout.addWidget(self.canvas)
        
        # Initialize serial thread and data storage
        self.serial_thread = SerialThread(port='/dev/ttyUSB0') # Adjust port here!
        self.serial_thread.data_received.connect(self.update_plot)
        self.x_data = []
        self.y_data = []
        self.time_counter = 0
        
        # Connect start/stop buttons (add these buttons to your UI first)
        self.ui.pushButtonStartSerial.clicked.connect(self.start_serial)
        self.ui.pushButtonStopSerial.clicked.connect(self.stop_serial)

    def start_serial(self):
        self.serial_thread.start()
        print("Serial plotting started")

    def stop_serial(self):
        self.serial_thread.stop()
        self.serial_thread.wait()
        print("Serial plotting stopped")

    def update_plot(self, new_data):
        # Update data lists
        self.time_counter += 1
        self.x_data.append(self.time_counter)
        self.y_data.append(new_data)
        
        # Keep plot clean by limiting data points (optional)
        if len(self.x_data) > 50:
            self.x_data.pop(0)
            self.y_data.pop(0)
        
        # Redraw the plot with new data
        self.ax.clear()
        self.ax.plot(self.x_data, self.y_data, 'b-', label='Serial Data')
        self.ax.set_xlabel('Time')
        self.ax.set_ylabel('Serial Data')
        self.ax.set_title('Real-Time Serial Plot')
        self.ax.legend()
        self.canvas.draw()

Raspberry Pi Specific Notes:

  • Adjust the serial port (/dev/ttyUSB0 or /dev/ttyAMA0 depending on your hardware setup)
  • Grant serial port permissions to your user: sudo usermod -a -G dialout $USER (log out and back in after this)
  • Modify the data parsing logic if your serial output isn't a single float (e.g., handle comma-separated values)

内容的提问来源于stack exchange,提问作者Chanuka Gayantha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 04:11:50