我试图测试QML以了解它如何与C++一起工作。我有ClassA
和ClassB
- 2个类似的C++类。这是一个ClassA
。所有的方法都是用自己的名字来解释,所以我不会在这里放置实现。QML内存管理
class ClassB;
class ClassA : public QObject
{
Q_OBJECT
public:
explicit ClassA(QObject *parent = 0);
~ClassA();
Q_PROPERTY(ClassB* classB READ getClassB WRITE setClassB NOTIFY classBChanged)
ClassB* getClassB() const;
void setClassB(ClassB *classB);
signals:
void classBChanged();
private:
ClassB *m_classB;
};
ClassB
是一样的,只是改变所有*lassA*
到*lassB*
和所有*lassB*
至*lassA*
。
然后我注册在QML都归类与
qmlRegisterType<ClassA>("testmodule.test",1,0,"ClassA");
qmlRegisterType<ClassB>("testmodule.test",1,0,"ClassB");
并在鼠标QML
代码单击创建两个对象是这样的:
onClicked: {
var comp = Qt.createComponent("TClassA.qml"); //TClassA.qml is
//a component of type
//ClassA
var ca = comp.createObject();
comp = Qt.createComponent("TClassB.qml");
var cb = comp.createObject();
ca.classB = cb;
cb.classA = ca;
parent.blockFromGC = ca;
}
此后,我称之为垃圾收集与gc()
。我预计ca
被阻止从parent.blockFromGC
删除和cb
被阻止从ca
删除参考。但垃圾收集器销毁cb
,之后parent.blockFromGC.classB === null
。
所以我有第二MouseArea
与此代码:
onClicked: {
console.log(mouse.button)
// if (mouse.button == Qt.RightButton) {
// console.log(parent.vasya.classB)
// }
gc();
console.log(parent.blockFromGC.classB) //I use cb here
}
所以,当我点击MouseArea
我在控制台中看到:
qml: 1 //Left button
qml: null //value of parent.blockFromGC.classB
classB destroyed: TQMLClassB(0x34960d0) //I have qDebug() in destructor
所以我的目标cb
被摧毁。
所以我有这样的问题:
1)是否有一种方法,我怎么能注册一个C++
型为基本型,这样我就可以 写var ca = new ClassA()
而不是创建一个*.qml
文件,创建一个组件,并最终创造一个东西?
2)为什么垃圾收集器破坏了我的cb
对象,我应该怎么做 以防止删除此对象?
此外!如果我取消注释那些注释行
// if (mouse.button == Qt.RightButton) {
// console.log(parent.vasya.classB)
// }
无论按下哪个按钮,对象都不会被销毁。
qml: 1 //left button
qml: TQMLClassB(0x3df8e90) //object is alive
.....
qml: 2 //right button
qml: TQMLClassB(0x3df8e90) //before gc() - alive
qml: TQMLClassB(0x3df8e90) //after gc() - alive
3)在哪里可以阅读关于QML
内存管理的详细资料?我觉得这种行为真的很奇怪..
加法1:我玩这种情况多一点,结果是不可预知的。我从5.3更新到Qt 5.4,这种删除对象的行为已经消失。问题在于行为如此不可预测,以至于我无法在Qt 5.4中重现这种行为,并不意味着问题得到解决。我会尝试查看错误报告和错误修复。如果我找到了什么,我会在这里发布。如果没有,我会尝试在Qt 5.4中重现这种情况并发布报告。
你可以把'ClassA'放入一个'Component'中,然后通过'var ca = thisComponent.createObject(parent)'创建它。至于对象破坏 - 你能确定在哪个步骤调用了desctructor?正如我所知道的,如果没有引用它,那么你就不得不以这种方式寻找对象。 – folibis
@folibis在调试模式下,这个问题成为一个概率问题。有时它发生了,有时并没有发生。跟踪没有给我太多的信息。如预期的那样,所有函数调用都在共享库中完成,其中一些已隐藏。而且它们都具有通常的名称,用于试图删除和反对的功能。无论如何,读一个补充发布,并感谢您的建议如何不需要创建* .qml文件。 – JustAnotherCurious