PyQt5 SplashScreen加载完成后主窗口无法显示直接退出问题
问题根因
进度走完程序直接退出的核心原因是变量作用域+Python垃圾回收机制:你在loading方法内部创建的MainWindow和ui都是方法级别的局部变量,当loading方法执行结束后,这两个局部变量没有任何外部引用,会被Python自动回收,对应的窗口对象刚执行完show()就被销毁,程序自然直接退出,和主窗口本身的代码逻辑无关。
修复方案
方案1:快速修复(改动最小)
把主窗口、UI实例绑定为SplashScreen类的实例属性,让对象生命周期和SplashScreen实例绑定,避免被垃圾回收。
修正后的loading方法代码如下:
def loading(self): # 设置进度条值 self.progressBar.setValue(self.counter) # 进度走完后跳转主窗口 if self.counter >= self.n: self.timer.stop() self.close() # 注意:不要用局部变量,绑定为self的属性 self.main_window = QtWidgets.QMainWindow() self.window_app = WindowApp() self.window_app.setupUi(self.main_window) self.main_window.show() self.counter += 1
方案2:规范实现(低耦合)
不建议在启动屏类内部直接耦合主窗口创建逻辑,可以给SplashScreen添加加载完成的自定义信号,在程序入口层监听信号创建主窗口,代码结构更清晰:
- 第一步:给SplashScreen类添加自定义信号
from PyQt5.QtCore import pyqtSignal class SplashScreen(QWidget): # 定义加载完成信号 load_finished = pyqtSignal() # 其余__init__、initUI代码保持原有逻辑不变
- 第二步:修改loading方法,进度走完时发射信号,不在类内部创建主窗口
def loading(self): self.progressBar.setValue(self.counter) if self.counter >= self.n: self.timer.stop() self.close() # 发射加载完成信号 self.load_finished.emit() self.counter += 1
- 第三步:修改程序入口代码,监听信号后创建主窗口
def show_main_window(): global main_window, ui main_window = QtWidgets.QMainWindow() ui = WindowApp() ui.setupUi(main_window) main_window.show() if __name__ == "__main__": app = QApplication(sys.argv) splash = SplashScreen() splash.show() # 监听加载完成信号,触发主窗口显示 splash.load_finished.connect(show_main_window) sys.exit(app.exec_())
注意:这里主窗口实例也要避免放在函数内部作为局部变量,要么声明为global全局变量,要么把主程序逻辑封装成类绑定为实例属性,否则同样会被垃圾回收导致窗口闪退。
内容的提问来源于stack exchange,提问作者Mama Mia
相关产品推荐
相关产品推荐

