PyQt5中嵌入Matplotlib图片无法更新的问题求助
解决PyQt中Matplotlib图片无法更新的问题
你的代码问题在于每次点击按钮都会新建一个FigureCanvas并添加到布局中,导致控件堆叠,而非更新原有画布。下面提供两种解决方案,推荐第一种复用画布的方式(更高效):
方案一:复用现有画布更新内容(推荐)
首先重构ImageDisplay类,它本身继承自FigureCanvas,无需额外创建画布实例:
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg from matplotlib.figure import Figure import numpy as np class ImageDisplay(FigureCanvasQTAgg): def __init__(self): # 调用父类构造函数创建Figure self.fig = Figure() super().__init__(self.fig) # 创建绘图轴 self.axes = self.fig.add_subplot(111) # 显示初始图片 self.axes.imshow(np.asarray(IMAGE)) self.draw() def nextImage(self): # 此处编写图片切换逻辑(比如更新IMAGE变量) # ...你的切换操作 self.UpdateImage() def UpdateImage(self): # 清除原有轴内容,避免图像重叠 self.axes.clear() # 绘制新图片 self.axes.imshow(np.asarray(IMAGE)) # 重新绘制画布 self.draw()
然后修改MainWindow类,直接复用ImageDisplay实例,无需重复创建控件:
from PyQt5 import QtWidgets class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): def __init__(self, *args, obj=None, **kwargs): super(MainWindow, self).__init__(*args, **kwargs) self.setupUi(self) self.imageDisp = ImageDisplay() layoutImage = self.Image_Area.layout() if layoutImage is None: layoutImage = QtWidgets.QVBoxLayout(self.Image_Area) # 直接添加ImageDisplay实例(本身就是画布控件) layoutImage.addWidget(self.imageDisp) self.NextImageButton.clicked.connect(self.inc) def inc(self): # 仅调用nextImage,由ImageDisplay自行更新画布 self.imageDisp.nextImage()
方案二:移除旧控件后添加新控件
如果坚持通过重建控件的方式更新,需要先移除布局中的旧画布并销毁,再添加新控件:
from PyQt5 import QtWidgets from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): def __init__(self, *args, obj=None, **kwargs): super(MainWindow, self).__init__(*args, **kwargs) self.setupUi(self) self.imageDisp = ImageDisplay() self.canvas_image = None layoutImage = self.Image_Area.layout() if layoutImage is None: layoutImage = QtWidgets.QVBoxLayout(self.Image_Area) ax_img = self.imageDisp.displayImage() self.canvas_image = FigureCanvasQTAgg(ax_img.figure) layoutImage.addWidget(self.canvas_image) self.NextImageButton.clicked.connect(self.inc) def inc(self): self.imageDisp.nextImage() layoutImage = self.Image_Area.layout() if layoutImage is None: layoutImage = QtWidgets.QVBoxLayout(self.Image_Area) # 移除并销毁旧画布,避免内存泄漏 if self.canvas_image: layoutImage.removeWidget(self.canvas_image) self.canvas_image.deleteLater() # 创建新画布并添加到布局 ax_img = self.imageDisp.UpdateImage() self.canvas_image = FigureCanvasQTAgg(ax_img.figure) layoutImage.addWidget(self.canvas_image) self.imageDisp.draw()
关键说明
- 方案一中,通过
axes.clear()清除原有内容,重新绘制新图后调用draw()更新画布,避免了控件重复创建和堆叠问题。 - 方案二中,必须调用
deleteLater()销毁旧控件,否则会造成内存泄漏,同时确保布局中始终只保留一个画布控件。
内容的提问来源于stack exchange,提问作者Amarth Gûl
相关产品推荐
相关产品推荐

