使用.ui文件的PySide小部件意外地被垃圾收集

时间:2016-01-15 23:59:32

标签: python qt garbage-collection pyside nuke

我有一个PySide QMainWindow,我在Nuke中运行。应用程序使用的某些小部件使用在Qt Designer中创建的.ui文件。

直到最近,QMainWindow课程才被授予父母。因此,当Nuke被最小化或改变焦点时,QMainWindow没有最小化或获得焦点。

为了解决这个问题,在创建QMainWindow时,我使用QApplication.activeWindow()方法获取一个对象以将QMainWindow作为父级提供。

parent = QApplication.activeWindow()
window = MyMainWindow(parent)

如果我这样做,QMainWindow将最小化并改变Nuke的焦点。但是,当访问使用.ui文件创建的任何窗口小部件的子窗口小部件时,它将引发异常

Traceback (most recent call last):
    ...
RuntimeError: Internal C++ object (PySide.QtGui.QPushButton) already deleted.

我使用方法very similar to this.ui文件加载到我的QWidget类

为什么要删除C ++对象(垃圾收集)?为QMainWindow指定父级时,为什么行为会发生变化?有没有另一种方法可以将QMainWindow设置为Nuke,以便在最小化和正确聚焦或以不同方式加载.ui文件而不会遇到此垃圾收集问题?

2 个答案:

答案 0 :(得分:2)

当其中一个父窗口小部件被垃圾收集时,会出现问题,因为不存在python对象引用。例如:

def create_window():
    parent = QApplication.activeWindow()
    window = MyMainWindow(parent)
    return window

当函数返回时,parent对象超出范围,它代表的C ++ pyobject最终将被垃圾收集。奇怪的是,这只是使用.ui文件创建的小部件的问题。解决方案是只保留对所有父对象的引用。我使用全局变量来存储对它们的引用。

GC_PROTECT = []

def create_window():
    parent = QApplication.activeWindow()
    GC_PROTECT.append(parent)
    window = MyMainWindow(parent)
    return window

答案 1 :(得分:0)

如果窗口被声明为Global,则在窗口本身关闭之前不会被销毁。所以你希望窗口/窗口小部件本身的引用继续存在于某个地方,而不是必需的父项(如前面的答案所述)

def create_window():
    parent = QApplication.activeWindow()
    # not necesarily the best practice to declare it here, but comfortable
    Global window
    window = MyMainWindow(parent)
    return window