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

如何在PyQt框架中嵌入Matplotlib图表?

把Matplotlib图表嵌入Qt主窗口的解决方案

你好呀!作为Stack Overflow新手,能主动尝试把图表嵌入界面已经超棒啦~ 你现在用plt.show()会弹出独立窗口,要把图表整合到Qt主窗口里,得用Matplotlib专门为Qt适配的后端组件,我来一步步帮你修改代码:

核心思路

我们需要把Matplotlib的Figure转换成Qt能识别的控件(用FigureCanvasQTAgg),然后把这个控件放到你的主窗口布局里,替代原来弹出新窗口的逻辑。

第一步:更新UI代码(dt.py)

首先给主窗口添加一个专门放图表的区域,同时调整整体布局让输入控件和图表区域合理分布:

try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    def _fromUtf8(s):
        return s
try:
    _encoding = QtGui.QApplication.UnicodeUTF8
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig)
class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName(_fromUtf8("MainWindow"))
        # 调大窗口尺寸,给图表留出空间
        MainWindow.resize(800, 600)
        self.centralwidget = QtGui.QWidget(MainWindow)
        self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
        
        # 创建主垂直布局,拆分输入区和图表区
        self.main_layout = QtGui.QVBoxLayout(self.centralwidget)
        self.main_layout.setObjectName(_fromUtf8("main_layout"))
        
        # 输入控件的水平子布局
        self.input_layout = QtGui.QHBoxLayout()
        self.input_layout.setSpacing(20)
        self.input_layout.setObjectName(_fromUtf8("input_layout"))
        
        self.label = QtGui.QLabel(self.centralwidget)
        self.label.setObjectName(_fromUtf8("label"))
        self.input_layout.addWidget(self.label)
        
        self.X1 = QtGui.QLineEdit(self.centralwidget)
        self.X1.setObjectName(_fromUtf8("X1"))
        self.input_layout.addWidget(self.X1)
        
        self.label_2 = QtGui.QLabel(self.centralwidget)
        self.label_2.setObjectName(_fromUtf8("label_2"))
        self.input_layout.addWidget(self.label_2)
        
        self.Y1 = QtGui.QLineEdit(self.centralwidget)
        self.Y1.setObjectName(_fromUtf8("Y1"))
        self.input_layout.addWidget(self.Y1)
        
        self.label_3 = QtGui.QLabel(self.centralwidget)
        self.label_3.setObjectName(_fromUtf8("label_3"))
        self.input_layout.addWidget(self.label_3)
        
        self.R1 = QtGui.QLineEdit(self.centralwidget)
        self.R1.setObjectName(_fromUtf8("R1"))
        self.input_layout.addWidget(self.R1)
        
        self.Generate = QtGui.QPushButton(self.centralwidget)
        self.Generate.setObjectName(_fromUtf8("Generate"))
        self.input_layout.addWidget(self.Generate)
        
        # 将输入布局加入主布局
        self.main_layout.addLayout(self.input_layout)
        
        # 新增图表容器
        self.chart_container = QtGui.QWidget(self.centralwidget)
        self.chart_container.setObjectName(_fromUtf8("chart_container"))
        self.chart_layout = QtGui.QVBoxLayout(self.chart_container)
        self.chart_layout.setObjectName(_fromUtf8("chart_layout"))
        self.main_layout.addWidget(self.chart_container)
        
        MainWindow.setCentralWidget(self.centralwidget)
        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None))
        self.label.setText(_translate("MainWindow", "X-Co-ordinate", None))
        self.label_3.setText(_translate("MainWindow", "Radii", None))
        self.Generate.setText(_translate("MainWindow", "Generate", None))
        self.label_2.setText(_translate("MainWindow", "Y-Co-ordinate", None))

第二步:修改主Python代码

导入Matplotlib的Qt后端组件,初始化图表控件,同时修改图表更新逻辑:

import os
import sys
import matplotlib.pyplot as plt
import matplotlib.patches as patches
from PyQt4 import QtGui, QtCore
from dt import Ui_MainWindow
# 导入Matplotlib的Qt适配组件
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt4agg import NavigationToolbar2QT as NavigationToolbar

class demoMainClass(QtGui.QMainWindow, Ui_MainWindow):
    aX1 = ("0")
    aY1 = ("0")
    aR1 = ("0")
    def __init__(self, parent=None):
        super(demoMainClass, self).__init__()
        self.setupUi(self)
        self.demoWindowInitialize()
        # 初始化图表控件
        self.init_chart()

    def demoWindowInitialize(self):
        self.X1.insert(self.aX1)
        self.Y1.insert(self.aY1)
        self.R1.insert(self.aR1)
        self.Generate.clicked.connect(self.demoFunction)

    def init_chart(self):
        # 创建Matplotlib的Figure和Axes
        self.fig = plt.figure()
        self.ax = self.fig.add_subplot(111, aspect='equal')
        # 将Figure转为Qt控件并添加到图表容器
        self.canvas = FigureCanvas(self.fig)
        self.chart_layout.addWidget(self.canvas)
        # 可选:添加Matplotlib导航工具栏(缩放、保存等功能)
        self.toolbar = NavigationToolbar(self.canvas, self.chart_container)
        self.chart_layout.addWidget(self.toolbar)

    def demoFunction(self):
        try:
            x1 = float(self.X1.text())
            y1 = float(self.Y1.text())
            r1 = float(self.R1.text())
            # 清空原有图表内容
            self.ax.clear()
            # 添加新的圆形
            self.ax.add_patch(patches.Circle((x1, y1), r1, fill=False))
            # 设置坐标轴范围,确保圆形完整显示
            self.ax.set_xlim(x1 - r1 - 1, x1 + r1 + 1)
            self.ax.set_ylim(y1 - r1 - 1, y1 + r1 + 1)
            # 刷新Canvas显示新图表
            self.canvas.draw()
        except ValueError:
            # 处理输入非数字的异常
            QtGui.QMessageBox.warning(self, "输入错误", "请输入有效的数字哦!")

if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    ui = demoMainClass()
    ui.show()
    sys.exit(app.exec_())

关键修改说明

  1. 布局优化:给主窗口添加了垂直布局,让输入控件和图表区域自动适配窗口大小,界面更规整。
  2. 图表嵌入逻辑:用FigureCanvasQTAgg把Matplotlib的绘图对象转换成Qt控件,直接嵌入到主窗口的图表容器中。
  3. 更新逻辑调整:不再创建新的Figure和调用plt.show(),而是在已有绘图区域上清空、重绘,再刷新控件显示,避免弹出独立窗口。
  4. 异常处理:增加了输入非数字的提示,让程序更健壮。

这样修改后,点击Generate按钮,图表就会直接显示在主窗口的下半部分啦~ 有任何问题都可以继续提问哦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:25:04