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

PyQt中第二个窗口打开后立即关闭的问题排查与修复求助

问题分析与修复方案

嘿,我一眼就揪出问题所在啦——你的第二个窗口打开就闪退,核心是局部变量生命周期太短,还有几个小细节需要调整,我一步步给你拆解:

问题1:局部变量导致窗口被立刻回收

在原来的start_clicked()函数里,你创建的window是个局部变量。当函数执行完最后一行代码后,Python的垃圾回收机制会自动销毁这个局部对象,窗口自然跟着关闭了。

问题2:主窗口引用不规范

你代码里的win.hide(),这里的win是main()函数里的局部变量,在全局的start_clicked()里直接访问其实是不规范的(没报错可能是你之前全局声明过,但这绝不是好的编码习惯)。

修复方案

最好的做法是把窗口切换逻辑整合到MainWindow类内部,把start_clicked改成类的方法,同时把新窗口保存为实例属性,让它的生命周期和主窗口绑定。

修改后的完整代码如下:

import sys
from PyQt5.QtWidgets import (QMainWindow, QLabel, QPushButton, QApplication, 
                             QMessageBox, QIcon)
from PyQt5.QtCore import pyqtSignal, QFont

class MainWindow(QMainWindow):
    switch_window = pyqtSignal(str)
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        # Initialize
        self.setGeometry(1000, 300, 1200, 800)
        self.setWindowTitle('Sensorlyze')
        self.setWindowIcon(QIcon('biosensor.jpg'))
        
        # Add Text
        l1 = QLabel("Welcome to SensorLyze", self)
        l1.move(25, 350)
        l1.setFont(QFont('Calibri',15))
        l1.adjustSize()
        
        l2 = QLabel("A software to simply sensor analytics", self)
        l2.move(25, 400)
        l2.setFont(QFont('Calibri', 10))
        l2.adjustSize()
        
        # Add Buttons
        button1 = QPushButton('Start', self)
        button1.resize(button1.sizeHint())
        # 改为连接到类的内部方法
        button1.clicked.connect(self.start_clicked)
        button1.move(60, 450)
        
        button2 = QPushButton('Exit', self)
        button2.resize(button2.sizeHint())
        button2.clicked.connect(self.exit_clicked)
        button2.move(240, 450)

    def start_clicked(self):
        # 将新窗口保存为实例属性,避免被垃圾回收
        self.second_window = QMainWindow()
        self.second_window.setGeometry(300, 500, 500, 500)
        self.second_window.setWindowTitle('Hello')
        self.second_window.show()
        # 用self.hide()直接操作当前主窗口实例
        self.hide()

    def exit_clicked(self):
        msgBox = QMessageBox()
        msgBox.setIcon(QMessageBox.Information)
        msgBox.setText("Are you sure you want to exit?")
        msgBox.setWindowTitle("Exit Sensorlyze")
        msgBox.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)
        msgBox.buttonClicked.connect(self.msgButtonClick)
        returnValue = msgBox.exec()
        if returnValue == QMessageBox.Ok:
            # 用PyQt规范的退出方式
            QApplication.instance().quit()

    def msgButtonClick(self, i):
        print("Button clicked is:", i.text())

stylesheet = """
QMainWindow {
    background-image: url("C:/Users/admin/Desktop/Sensorlyze/biosensor.jpg");
    background-repeat: no-repeat;
    background-position: center;
}
"""

def main():
    app = QApplication(sys.argv)
    app.setStyleSheet(stylesheet)
    win = MainWindow()
    win.show()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

关键修改点说明

  • 把start_clicked、exit_clicked、msgButtonClick都改成了MainWindow类的方法,所有窗口操作都封装在类内部,更符合面向对象设计规范。
  • 新窗口self.second_window作为实例属性存在,只要主窗口实例没被销毁,它就会一直保留,不会被垃圾回收。
  • 用self.hide()代替原来的win.hide(),直接操作当前主窗口实例,彻底摆脱全局变量的依赖。
  • 退出操作改用QApplication.instance().quit(),比直接调用exit()更符合PyQt的运行逻辑。

这样修改后,点击Start按钮打开的第二个窗口就不会闪退啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 16:12:44