我正在开发一个简单的应用来演示C ++与QML的集成,但我遇到了问题。简而言之,我想在qml中创建一个C ++对象,并将其传递给C ++进行处理。这是我的代码。
import QtQuick 2.4
import QtQuick.Window 2.2
import test 1.0
Window {
visible: true
MainForm {
anchors.fill: parent
mouseArea.onClicked: {
console.log("clicked")
var student = Qt.createComponent("Student")
student.name = "Hello frome QML";
console.log( student.name ) // good
school.addStudent( student )
}
}
}
Student.h
#ifndef STUDENT_H
#define STUDENT_H
#include <QObject>
class Student : public QObject
{
Q_OBJECT
QString m_name;
public:
explicit Student(QObject *parent = 0);
~Student();
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
QString name() const
{
return m_name;
}
signals:
void nameChanged(QString arg);
public slots:
void setName(QString arg)
{
if (m_name == arg)
return;
m_name = arg;
emit nameChanged(arg);
}
};
#endif // STUDENT_H
现在当我addStudent()
到学校课堂时,有麻烦的地方。关注.cpp文件如下。
#include "school.h"
#include <QDebug>
School::School(QObject *parent) : QObject(parent)
{
}
School::~School()
{
}
// why does this not work? it cause compiler error..can't access private members of QObject
//void School::addStudent(Student student)
//{
//// students.append( &student );
//// qDebug() << "added";
//// qDebug() << student.name();// << " was added to school";
//}
void School::addStudent(Student * student)
{
students.append( student );
qDebug() << "added";
qDebug() << student->name();// if this line is there, it breaks the application
}
问题也在代码中的注释中,但摘要是:
当我尝试访问student.name时,为什么addStudent()会崩溃?我在设置之后可以在qml文件中访问它。
如果我按照代码中的值传递Student
,为什么我的项目无法编译?
其他想法
似乎它可能与C ++对象被C ++函数执行时被破坏有关。在QML中创建的C ++对象的生命周期是什么?什么时候被摧毁?对象的生命周期可能会成为问题吗?
答案 0 :(得分:2)
假设您通过cpp文件中的Student
将qmlRegisterType
类型注册到QML。
在您的QML中,Qt.createComponent("Student")
不会创建Student
个对象,而是QQmlComponent
。尝试设置name
以外的属性,但它仍然有效,因为对象不是 a Student
。相反,您应该通过Component.createObject:
MainForm {
id: mainForm
mouseArea.onClicked: {
var student = studentComponent.createObject(mainForm);
student.name = "Hello frome QML";
school.addStudent( student );
}
Component {
id: studentComponent
Student{}
}
}
现在一切正常。
返回您的代码,
//QML
var student = Qt.createComponent("Student")
student.name = "Hello frome QML";
console.log( student.name ) // good
不,它不好。 student.abcdefg = "Hello from QML"
也有效。添加console.log(student)
,您可以看到student
不是Student
。
为什么addStudent()在尝试访问student.name时崩溃?我在设置它之后可以在qml文件中访问它。
由于从QML传递的对象不是指针Student
,因此崩溃了。 QML引擎将空指针传递给此函数。您在QML中访问的内容不是Student
。
如果我按照代码中的值传递
Student
,我的项目为什么不编译?
因为Student
是QObject
,因此无法复制。改为通过指针。
在QML中创建的C ++对象的生命周期是什么?什么时候被摧毁?对象的生命周期可能会成为问题吗?
生命周期在QML中不是问题,因为您创建的是组件,而不是对象。在此答案中创建Student
对象时,
var student = studentComponent.createObject(mainForm);
新创建的对象设置mainForm
作为其父级。在mainForm
被释放之前,该对象不会被删除。除非您明确删除它。
答案 1 :(得分:0)
尝试将类Student的声明中的函数QString name() const
的声明移到Q_PROPERTY宏之前。或者在名称功能之前再次指定“public:”。宏正在将访问说明符重置为“private”。