QML 未能检测到在 C++ 中破坏的 QObject

Posted

技术标签:

【中文标题】QML 未能检测到在 C++ 中破坏的 QObject【英文标题】:QML failing to detect QObject destroyed in C++ 【发布时间】:2014-06-28 11:27:08 【问题描述】:

呈现的代码执行以下操作:

创建 QObject 派生类的对象并将其公开给 QML

该类有一个指向另一个 QObject 派生类的指针,并且 QML 可以通过 Q_PROPERTY 访问该指针。

QML 中的 MouseArea 检测到用户单击,并简单地询问 c++ 代码以删除要删除的指针。

一旦检测到,矩形的颜色就会变成黑色。

问题在于,虽然某些方法可以检测到 c++ 删除指针的情况,但其他方法却不能。

查看内联 cmets:

(1)和(1b)作品的结合

(1) 和 (1d) 的组合不起作用

(2) 单独工作,但 (3) 单独不工作。

当一切正常时,您应该会看到 Rectangle 的颜色从黄色变为黑色。

有人可以解释一下这种行为吗?

CPP 代码:

class Name : public QObject

   Q_OBJECT
   Q_PROPERTY(bool boolVal READ boolVal CONSTANT FINAL)
public:
   bool boolVal() const return true;
;

class Root : public QObject

   Q_OBJECT
   Q_PROPERTY(QObject* name READ name CONSTANT FINAL)
public:
   QObject* name() const return m_pName;
   Q_INVOKABLE void deleteName() delete m_pName; m_pName = 0;
private:
   Name *m_pName new Name;
;

//--- main
int main(int argc, char *argv[])

    QGuiApplication app(argc, argv);

    Root objRoot;
    QtQuick2ApplicationViewer viewer0;
    viewer0.rootContext()->setContextProperty("objRoot", &objRoot);
    viewer0.setMainQmlFile(QStringLiteral("qml/dualWindowApp/main.qml"));
    viewer0.showExpanded();

    return app.exec();

QML 代码:

import QtQuick 2.0

Rectangle 
    width: 360
    height: 360

    color: "red"

    Rectangle 
       id: objRect
       anchors left: parent.left; top: parent.top
       height: 70; width: 70;

       property bool checked
       property QtObject temp: objRoot.name

       color: checked ? "yellow" : "black"                                 //                        (1)

       //color: objRect.temp && objRect.temp.boolVal ? "yellow" : "black"  //--->WORKS               (2)
       //color: objRoot.name && objRoot.name.boolVal ? "yellow" : "black"  //--->DOES NOT WORK !!!   (3)

       Binding on checked 
          //value: objRect.temp && objRect.temp.boolVal                    //--->DOES NOT WORK !!!   (1a)
          //value: objRect.temp !== null && objRect.temp.boolVal           //--->WORKS               (1b)
          value: objRect.temp ? objRect.temp.boolVal : false               //--->WORKS               (1c)

          //Using directly without collecting in local QtQobject temp:
          //----------------------------------------------------------
          //value: objRoot.name && objRoot.name.boolVal                    //--->DOES NOT WORK !!!   (1d)
          //value: objRoot.name !== null && objRoot.name.boolVal           //--->DOES NOT WORK !!!   (1e)
          //value: objRoot.name ? objRoot.name.boolVal : false             //--->DOES NOT WORK !!!   (1f)
       

       Text 
           text: "Destroy"
           anchors.centerIn: parent
       

       MouseArea 
           anchors.fill: parent
           onClicked: objRoot.deleteName()
       
    

使用:Qt/QML 5.2.0, Win 7, MinGW 4.8, QtQuick 2.0

【问题讨论】:

【参考方案1】:

你的属性声明在我看来很奇怪:name 显然可以改变,但你已经声明了它CONSTANT。我的猜测是,如果没有CONSTANT,它会工作得更好,而是提供nameChangednameChanged 信号的NOTIFY,当name 的值发生变化时发出,否则不能保证QML 状态绑定到C++ 属性将被更新。

【讨论】:

我明白你说的。这就是我通常所做的。但对于 QObject*,我认为 QML 以某种方式理解被破坏的 c++ 对象。即使您没有在删除后将 nullptr 显式分配给 c++ 成员指针m_pName,工作的代码仍然会收到绑定 QtObject 为空的通知。 这是怎么发生的? 即使你有一个通知器,你什么时候发出它?指针本身不会改变,只有指针被删除,这可以通过许多不同的机制发生(例如,通过 Qt 的父子内存管理等静默方式)

以上是关于QML 未能检测到在 C++ 中破坏的 QObject的主要内容,如果未能解决你的问题,请参考以下文章

如何从 QML 连接 C++ 对象的破坏信号?

我未能在 QML 中滑动屏幕动画

QML 在 ListView 中显示的相机照片被破坏

QML在ListView中显示的相机照片被破坏

Qt QML - QModBus 读取被 QML BusyIndi​​cator/Animation 破坏 - SingleThread

检测鼠标光标何时在 Qt5 和 QML 中的不规则形状图片上