PyQt5子窗口创建后自动关闭问题求助
问题描述
我正在使用Python和PyQt5开发程序,这是我首次使用PyQt5。程序启动后主窗口弹出,用户可通过两个按钮选择操作;点击按钮会打开新的子窗口供用户填写字段,但子窗口每次打开后都会立刻关闭。以下是我的代码:
main.py
import sys from PyQt5.QtWidgets import QApplication, QWidget, QGridLayout, QFormLayout, QGroupBox, QLabel, QLineEdit, \ QComboBox, QTextEdit, QPushButton, QTreeView, QMenuBar, QMainWindow from PyQt5.QtGui import QStandardItemModel from scelle_window import ScelleWindow from oe_window import OeWindow class MainWindow(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle('''Main Window''') self.resize(800, 500) main_widget = QWidget() self.setCentralWidget(main_widget) grid = QGridLayout() bt_add_scelle = QPushButton('''Add objetc''') bt_add_scelle.clicked.connect(self.add_scelle_dial) bt_add_oe = QPushButton('''Add desc''') bt_add_oe.clicked.connect(self.add_oe_dial) grpbox_tree = QGroupBox('''List''') layout_tree = QGridLayout() layout_tree.addWidget(case_tree, 0, 0) layout_tree.addWidget(bt_add_scelle, 1, 0) layout_tree.addWidget(bt_add_oe, 2, 0) grpbox_tree.setLayout(layout_tree) grid.addWidget(grpbox_tree, 3, 0, 1, 2) main_widget.setLayout(grid) def add_scelle_dial(self): desc_scelle = ScelleWindow() desc_scelle.show() def add_oe_dial(self): desc_oe = OeWindow() desc_oe.show() if __name__ == '__main__': app = QApplication(sys.argv) win = MainWindow() win.show() sys.exit(app.exec_())
scelle_window.py
from PyQt5.QtWidgets import QWidget, QFormLayout, QLabel, QLineEdit, QComboBox class ScelleWindow(QWidget): def __init__(self): super().__init__() self.setWindowTitle('''Object informations''') self.resize(500, 300) # ... following code...
oe_window.py
from PyQt5.QtWidgets import QWidget, QFormLayout, QLabel, QLineEdit, QComboBox class OeWindow(QWidget): def __init__(self): super().__init__() self.setWindowTitle('''Object description''') self.resize(500, 300) # ... following code...
请问这是由垃圾回收(garbage collection)导致的,还是其他原因?
问题原因与解决方案
这确实是垃圾回收导致的问题。
在add_scelle_dial和add_oe_dial方法中,你创建的子窗口对象(desc_scelle、desc_oe)是局部变量,当方法执行完毕后,这些变量会失去引用,Python的垃圾回收机制会立即销毁它们,对应的窗口也就随之关闭了。
解决方案1:绑定为实例属性
把子窗口对象绑定到主窗口的实例属性上,让它们始终持有引用:
def add_scelle_dial(self): self.desc_scelle = ScelleWindow() self.desc_scelle.show() def add_oe_dial(self): self.desc_oe = OeWindow() self.desc_oe.show()
解决方案2:支持多窗口同时打开
如果需要允许同时打开多个同类型子窗口,可以用列表存储所有子窗口实例:
class MainWindow(QMainWindow): def __init__(self): super().__init__() # 初始化子窗口存储列表 self.child_windows = [] # ... 其他原有初始化代码 ... def add_scelle_dial(self): desc_scelle = ScelleWindow() self.child_windows.append(desc_scelle) desc_scelle.show() def add_oe_dial(self): desc_oe = OeWindow() self.child_windows.append(desc_oe) desc_oe.show()
通过以上两种方式,都能保证子窗口不会因为失去引用被垃圾回收,从而正常保持打开状态。
内容的提问来源于stack exchange,提问作者Ju Ctn
相关产品推荐
相关产品推荐

