如何管理动态分配QObject的生命周期返回QML?

时间:2014-12-05 11:34:33

标签: c++ qt garbage-collection qml dynamic-allocation

我有这段代码:

QVariant componentFromCode(QString code) {
    QQmlComponent * component = new QQmlComponent(engine);
    engine->setObjectOwnership(component, QQmlEngine::JavaScriptOwnership);
    connect(component, &QQmlComponent::destroyed, this, &Factory::echo);
    component->setData(code.toUtf8(), QUrl());
    return QVariant::fromValue(component);
}

但永远不会调用Factory::echo(),这意味着每次调用函数时对象都会泄露。

这就是我在QML方面所拥有的:

onClicked: {          
    var code =
        'import QtQuick 2.3
        Rectangle {
            width: 50
            height: 50
            color: "blue"
        }
        '

    stack.push(Factory.componentFromCode(code))
    gc()
}

我明确设置了对象所有权,并显式调用gc()来强制进行垃圾回收,但destroyed()信号永远不会被发出,因此对象永远不会被删除。根据我的阅读,这应该在QML中自动发生。

请注意,它适用于:

var comp = Factory.componentFromCode(code)
stack.push(comp)
comp.destroy()

但这只是不方便,我想让对象自动销毁,因为它超出了范围,或者只要它被QML代码引用就会保持活着,并且当它是不再需要,在许多情况下手动操作可能很难/荒谬。

编辑:堆栈示例碰巧是我的实际代码,但我想这不是一个好例子,看看堆栈是如何承担对组件的所有权的。即使在如此简单的情况下,我也无法获得任何终身管理:

function JSfoo() {
    var obj = CXTProp.getCppQObjectStar()
    console.log(obj.objectName)
} // QObject is not collected here

...或

QtObject {
    property QtObject: CXTProp.getCppQObjectStar()
} // QObject is not collected after the object is destroyed

1 个答案:

答案 0 :(得分:4)

我不认为物体在泄漏。试试这个:

class TestObj : public QObject {
     Q_OBJECT
public:
    ~TestObj() { qDebug() << "destructor called"; }
};

class Test : public QObject {
    Q_OBJECT
public:
    explicit Test(QObject *parent = 0) : QObject(parent) {}
public slots:
    QVariant getObject() {
        QObject * obj = new TestObj;
        obj->setObjectName("that object");
        connect (obj, &TestObj::destroyed, this, &Test::echo);
        return QVariant::fromValue(obj);
    }
    void echo() { qDebug() << "it got destroyed"; }
};

和QML:

function test() {
    var test = Test.getObject()
    console.log(test.objectName)
}

在收集test()对象后,当您关闭应用程序时,永远不会触发echo()插槽,但析构函数中的调试语句确实显示在控制台中:

qml: that object
destructor called

如果你在函数范围内调用gc()它不起作用,可能是因为该对象仍在其中引用:

function test() {
    var test = Test.getObject()
    console.log(test.objectName)
    gc() // doesn't do anything
}

但是,如果你这样做:

function test2() {
    test()
    gc()
}

它有效,因为在对象的引用超出范围之后触发了垃圾收集:

qml: that object
destructor called
it got destroyed

似乎当应用程序存在时,它不会处理destroyed()信号,因此永远不会触发echo()插槽,这可能是误导您相信对象泄漏不受管理的原因。我不确定这是Qt设计的产品还是一个bug。 Test对象在main()的堆栈中实例化,所以它应该仍然是#34; alive&#34;当由QML管理的对象被销毁时,应该是它使用的事件循环,所以我希望在应用程序退出之前看到echo(),但似乎情况并非如此。但这不是问题的范围,问题的关键是对象被管理,并且当它们不再被引用并且触发垃圾收集时将被收集。

相关问题