如何管理返回QML的动态分配的QObject的生命周期? [英] How to manage lifetime of dynamically allocated QObject returned to QML?

查看:1697
本文介绍了如何管理返回QML的动态分配的QObject的生命周期?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个代码:

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

Factory :: echo c $ c>永远不会被调用,这意味着每次调用函数时对象都会泄露。



这是我在QML端的功能:

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

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

我显式设置对象所有权,并显式调用 gc()强制垃圾收集, code> destroyed()信号从不被发射,因此对象永远不会被删除。从我读的这个应该是在QML自动发生。



注意它适用于:

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

但它只是不方便,我想让对象自动销毁,因为它超出范围,或者,只要它是由QML代码引用,并在不再需要时被销毁,在许多情况下可能很难/荒谬地手动执行。



编辑:堆栈示例发生在是我的实际代码,但我想这不是一个好例子,看看如何栈取所有权的组件。我甚至在这样简单的情况下也不会得到任何生命周期的管理:

  function JSfoo(){
var obj = CXTProp.getCppQObjectStar()
console.log(obj.objectName)
} //此处不收集QObject

或...

  QtObject {
property QtObject:CXTProp.getCppQObjectStar )
} //在对象被销毁之后不会收集QObject


解决方案

我不认为对象泄漏。试试这个:

  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()< 它被毁了; }
};

并在QML中:

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

test()后,不收集对象, , echo()插槽从未被触发,但是析构函数的debug语句确实显示在控制台中:

  qml:该对象
析构函数称为

如果在函数的作用域中调用 gc(),它不起作用,可能是因为该对象仍然引用它:

  function test(){
var test = Test.getObject()
console.log(test.objectName)
gc ()//不做任何事情
}

但是, :

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

它工作原理,因为垃圾收集是在引用对象超出范围后触发的:

  qml:该对象
析构函数称为
被销毁

看来当应用程序存在时,它不处理 destroyed()信号,所以 echo()插槽从来没有触发,这可能是什么误导你相信对象泄漏非托管。我不知道这是否是Qt的设计或错误的产品。 Test 对象在 main()中的栈上被实例化,所以当对象,由QML管理的应用程序应该是它使用的事件循环,所以我希望在应用程序退出之前看到 echo(),但似乎这不是案件。但这不是问题的范围,问题的关键是对象是管理的,当他们不再被引用和垃圾回收被触发时,它们将被收集。


I have this code:

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);
}

But Factory::echo() is never called, which means the object gets leaked every time the function is called.

This is what I have on the QML side:

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

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

I explicitly set the object ownership, and explicitly call gc() to force garbage collection, but the destroyed() signal never gets emitted, therefore the object never gets deleted. From what I read this is supposed to happen automatically in QML.

Note that it works to:

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

But it is just not convenient, I'd like to have the object destroyed automatically as it falls out of scope, or alternatively, remain alive for as long as it is referenced by QML code and be destroyed when it is no longer needed, something that might be hard/absurd to do manually in many situations.

EDIT: The stack example happened to be my actual code, but I guess it is not that good of an example, seeing how the stack taking ownership over the component is assumed. I don't get any lifetime management even in such simple cases as:

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

or...

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

解决方案

I don't think the object is leaking. Try this out:

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"; }
};

and in QML:

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

After test() the object isn't collected, and when you close the application, the echo() slot is never triggered, but the debug statement from the destructor is indeed showing up in the console:

qml: that object
destructor called

If you call gc() in the scope of the function it doesn't work, probably because the object is still referenced in it:

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

However, if you do it like that:

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

It works, because the garbage collection is triggered after the reference to the object has fallen out of scope:

qml: that object
destructor called
it got destroyed

It seems that when the application exists, it doesn't handle the destroyed() signal, so the echo() slot is never triggered which is probably what misled you into believing the object is leaking unmanaged. I am not sure if this is a product of Qt's design or a bug. The Test object is instantiated on the stack in main() so it should definitely still be "alive" when objects, managed by QML are being destroyed, as should be the event loop it uses, so I would expect to see echo() before the application exits, but it seems this is not the case. But that's not the scope of the question, point of the matter is objects are managed and will be collected when they are no longer referenced and garbage collection is triggered.

这篇关于如何管理返回QML的动态分配的QObject的生命周期?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆