如何在PyQt5中更新Widget画布以刷新Matplotlib图表?
问题解决:PyQt5中Matplotlib图表点击按钮无法刷新的问题
问题现象
点击按钮会基于10个随机整数生成Matplotlib图表,首次点击可正常显示,但后续点击图表无变化,无法刷新。
问题根源
原代码每次点击按钮时都会新建一个MplCanvas实例和QVBoxLayout,然后重复给self.widget设置布局。Qt中重复设置布局会导致旧的控件和布局未被正确清理,新的canvas无法正常替换显示。正确的做法应该是复用已有的绘图画布,仅更新绘图数据并刷新画布。
修改后的代码
main.py
import sys import numpy as np from PyQt5 import uic from PyQt5 import QtWidgets from PyQt5.QtWidgets import * from matplotlib.figure import Figure from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg [form_class, QMainWindow] = uic.loadUiType('myuifile.ui') class MplCanvas(FigureCanvasQTAgg): def __init__(self): fig = Figure() self.axes = fig.add_subplot(111) super(MplCanvas, self).__init__(fig) class Main(form_class, QMainWindow): def __init__(self): super(Main, self).__init__() self.setupUi(self) # 初始化时就创建画布并添加到widget的布局中 self.canvas = MplCanvas() layout = QtWidgets.QVBoxLayout(self.widget) layout.addWidget(self.canvas) self.pushButton.clicked.connect(self.plot_graph) def plot_graph(self): x = range(10) y = np.random.randn(10) # 清除旧的绘图内容 self.canvas.axes.clear() # 绘制新的图表 self.canvas.axes.plot(x, y) # 刷新画布 self.canvas.draw() if __name__ == '__main__': app = QApplication(sys.argv) main = Main() main.show() app.exec_()
myuifile.ui
<?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>Form</class> <widget class="QWidget" name="Form"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>496</width> <height>404</height> </rect> </property> <property name="windowTitle"> <string>Form</string> </property> <layout class="QGridLayout" name="gridLayout"> <item row="0" column="0"> <widget class="QPushButton" name="pushButton"> <property name="font"> <font> <family>Consolas</family> <weight>75</weight> <bold>true</bold> </font> </property> <property name="text"> <string>PushButton</string> </property> </widget> </item> <item row="0" column="1"> <spacer name="horizontalSpacer"> <property name="orientation"> <enum>Qt::Horizontal</enum> </property> <property name="sizeHint" stdset="0"> <size> <width>376</width> <height>20</height> </size> </property> </spacer> </item> <item row="1" column="0" colspan="2"> <widget class="QWidget" name="widget" native="true"> <property name="font"> <font> <family>Consolas</family> <weight>75</weight> <bold>true</bold> </font> </property> <property name="autoFillBackground"> <bool>false</bool> </property> <property name="styleSheet"> <string notr="true">background-color: rgb(255, 255, 255);</string> </property> </widget> </item> </layout> </widget> <resources/> <connections/> </ui>
效果说明
修改后,每次点击按钮时:
- 会先清除画布上的旧图表
- 绘制新的随机数据图表
- 立即刷新画布,实现图表的实时更新
应用界面说明:顶部左侧是一个Consolas加粗字体的按钮,右侧为水平占位空间,下方是白色背景的区域用于显示Matplotlib图表。
内容的提问来源于stack exchange,提问作者agile
相关产品推荐
相关产品推荐

