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

PyQt6点击按钮时如何更新Widget内容?图表二次更新失效求解

问题分析与解决方案

你的核心问题在于每次点击按钮都重复创建新的MyCanvas实例和布局,并调用setLayout——QWidget在已有布局的情况下重复设置布局不会正确触发界面刷新,这就是首次点击有效、后续无变化的原因。不需要更换承载Matplotlib的Widget类型,只需要调整更新逻辑,复用已有的画布组件即可。

修复思路

  1. 初始化时就创建唯一的MyCanvas实例,并将其添加到new_window的布局中,避免重复创建布局和画布。
  2. 给MyCanvas添加一个专门的更新方法,负责清除旧图表、绘制新内容并刷新画布。
  3. 点击按钮时,调用这个更新方法传入对应的数据,而不是重新创建整个画布和布局。

修改后的完整代码

import sys

from PyQt6.QtWidgets import QApplication, QWidget, QPushButton, QHBoxLayout, QVBoxLayout
from matplotlib.backends.backend_qtagg import FigureCanvasQTAgg
from matplotlib.figure import Figure

class MyCanvas(FigureCanvasQTAgg):
    def __init__(self, parent=None, width=5, height=4, dpi=100):
        self.fig = Figure(figsize=(width, height), dpi=dpi)
        self.axes = self.fig.add_subplot(111)
        super(MyCanvas, self).__init__(self.fig)

    def update_plot(self, data, labels, title):
        # 清除当前轴的内容
        self.axes.clear()
        # 绘制新的饼图
        self.axes.pie(data, labels=labels)
        self.axes.set_title(title)
        # 刷新画布
        self.draw()

class MyWindow(QWidget):
    def __init__(self, *args, **kwargs):
        super(MyWindow, self).__init__(*args, **kwargs)
        self.new_window = QWidget()
        self.new_window.setFixedSize(400, 600)

        # 初始化画布并添加到new_window的布局中
        self.canvas = MyCanvas(self, width=5, height=5, dpi=100)
        layout = QHBoxLayout()
        layout.addWidget(self.canvas)
        self.new_window.setLayout(layout)

        self.button1 = QPushButton('1')
        self.button2 = QPushButton('2')

        self.box_button = QHBoxLayout()
        self.box_button.addWidget(self.button1)
        self.box_button.addWidget(self.button2)

        self.box_new = QVBoxLayout()
        self.box_new.addWidget(self.new_window)
        self.box_new.addLayout(self.box_button)

        self.button1.clicked.connect(self.click1)
        self.button2.clicked.connect(self.click2)

        self.setLayout(self.box_new)

    def click1(self):
        cars = ['1', '2', '3', '4']
        data = [11, 22, 33, 44]
        # 调用画布的更新方法
        self.canvas.update_plot(data, cars, 'title_1')

    def click2(self):
        cars = ['11', '22', '33']
        data = [111, 222, 333]
        # 调用画布的更新方法
        self.canvas.update_plot(data, cars, 'title_2')

if __name__ == '__main__':
    app = QApplication(sys.argv)
    main_window = MyWindow()
    main_window.show()
    sys.exit(app.exec())

关键说明

  • update_plot方法中,self.axes.clear()会清除当前轴的所有内容,避免新旧图表重叠;self.draw()会强制刷新画布,确保新内容显示。
  • 初始化时只创建一次画布和布局,后续点击仅更新数据,既节省资源又能正确触发界面刷新。
  • 不需要调用update()或repaint(),Matplotlib的draw()方法已经能正确通知Qt刷新界面。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 02:55:35