如何在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_())
关键修改说明
- 布局优化:给主窗口添加了垂直布局,让输入控件和图表区域自动适配窗口大小,界面更规整。
- 图表嵌入逻辑:用
FigureCanvasQTAgg把Matplotlib的绘图对象转换成Qt控件,直接嵌入到主窗口的图表容器中。 - 更新逻辑调整:不再创建新的
Figure和调用plt.show(),而是在已有绘图区域上清空、重绘,再刷新控件显示,避免弹出独立窗口。 - 异常处理:增加了输入非数字的提示,让程序更健壮。
这样修改后,点击Generate按钮,图表就会直接显示在主窗口的下半部分啦~ 有任何问题都可以继续提问哦!
内容的提问来源于stack exchange,提问作者Shubham Kuse
相关产品推荐
相关产品推荐

