PyQt5调用close()误关主窗口,求仅关闭子窗口的方法
PyQt5子窗口关闭时误关主窗口的解决方法
问题场景
使用PyQt5开发GUI程序时,主窗口按钮可打开包含stackedWidget的子窗口,但点击子窗口的“Finish”按钮调用self.close()时,主窗口会一并关闭,需求是仅关闭子窗口。
问题根源
- 子窗口的
Ui_screen1类自定义了递归的close()方法,该方法未调用Qt窗口的原生关闭逻辑,反而无限递归自身,同时覆盖了窗口的原生关闭方法。 - UI类未正确关联到子窗口的
QMainWindow实例,调用self.close()时无法正确指向子窗口对象,导致触发错误的关闭逻辑。
解决步骤
- 删除自定义递归
close()方法:移除Ui_screen1中定义的def close(self): self.close(),恢复Qt窗口的原生关闭逻辑。 - 直接绑定子窗口实例的关闭方法:在按钮点击事件中,直接调用传入的
MainWindow实例的close()方法,确保关闭的是子窗口。 - 修正UI布局细节:调整子窗口菜单栏宽度与窗口一致,避免布局异常。
修改后的子窗口screen1代码
from PyQt5 import QtCore, QtGui, QtWidgets class Ui_screen1(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(384, 567) self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") # 直接绑定子窗口实例的close方法 self.button = QtWidgets.QPushButton(self.centralwidget, clicked=MainWindow.close) self.button.setGeometry(QtCore.QRect(120, 260, 131, 51)) self.button.setObjectName("buton") MainWindow.setCentralWidget(self.centralwidget) self.menubar = QtWidgets.QMenuBar(MainWindow) # 修正菜单栏宽度与窗口一致 self.menubar.setGeometry(QtCore.QRect(0, 0, 384, 21)) self.menubar.setObjectName("menubar") MainWindow.setMenuBar(self.menubar) self.statusbar = QtWidgets.QStatusBar(MainWindow) self.statusbar.setObjectName("statusbar") MainWindow.setStatusBar(self.statusbar) self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "子窗口")) self.button.setText(_translate("MainWindow", "Close")) if __name__ == "__main__": import sys app = QtWidgets.QApplication(sys.argv) MainWindow = QtWidgets.QMainWindow() ui = Ui_screen1() ui.setupUi(MainWindow) MainWindow.show() sys.exit(app.exec_())
修改后的Finish按钮事件代码
def click_next(self): if self.next.text() != "Finish>": if self.stackedWidget.currentIndex() != 2: self.stackedWidget.setCurrentIndex(self.stackedWidget.currentIndex() + 1) else: self.next.setText("Finish>") self.stackedWidget.setCurrentIndex(self.stackedWidget.currentIndex() + 1) else: # 通过parent()获取子窗口实例并关闭 self.parent().close()
优化后的主窗口代码
from PyQt5 import QtCore, QtGui, QtWidgets from screen1 import Ui_screen1 class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(584, 567) self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.button = QtWidgets.QPushButton(self.centralwidget, clicked=self.gotoscreen1) self.button.setGeometry(QtCore.QRect(220, 260, 131, 51)) self.button.setObjectName("buton") MainWindow.setCentralWidget(self.centralwidget) self.menubar = QtWidgets.QMenuBar(MainWindow) self.menubar.setGeometry(QtCore.QRect(0, 0, 584, 21)) self.menubar.setObjectName("menubar") MainWindow.setMenuBar(self.menubar) self.statusbar = QtWidgets.QStatusBar(MainWindow) self.statusbar.setObjectName("statusbar") MainWindow.setStatusBar(self.statusbar) self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow) def gotoscreen1(self): self.window = QtWidgets.QMainWindow() self.ui = Ui_screen1() self.ui.setupUi(self.window) self.window.show() def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "主窗口")) self.button.setText(_translate("MainWindow", "打开子窗口")) if __name__ == "__main__": import sys app = QtWidgets.QApplication(sys.argv) MainWindow = QtWidgets.QMainWindow() ui = Ui_MainWindow() ui.setupUi(MainWindow) MainWindow.show() sys.exit(app.exec_())
内容的提问来源于stack exchange,提问作者Nir Eyal
相关产品推荐
相关产品推荐

