将对象从QML传递到C ++

时间:2015-05-11 20:16:46

标签: c++ qt qml qtquick2

我正在开发一个简单的应用来演示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
}

问题也在代码中的注释中,但摘要是:

  1. 当我尝试访问student.name时,为什么addStudent()会崩溃?我在设置之后可以在qml文件中访问它。

  2. 如果我按照代码中的值传递Student,为什么我的项目无法编译?

  3. 其他想法

    似乎它可能与C ++对象被C ++函数执行时被破坏有关。在QML中创建的C ++对象的生命周期是什么?什么时候被摧毁?对象的生命周期可能会成为问题吗?

2 个答案:

答案 0 :(得分:2)

假设您通过cpp文件中的StudentqmlRegisterType类型注册到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,我的项目为什么不编译?

因为StudentQObject,因此无法复制。改为通过指针。

  

在QML中创建的C ++对象的生命周期是什么?什么时候被摧毁?对象的生命周期可能会成为问题吗?

生命周期在QML中不是问题,因为您创建的是组件,而不是对象。在此答案中创建Student对象时,

var student = studentComponent.createObject(mainForm);

新创建的对象设置mainForm作为其父级。在mainForm被释放之前,该对象不会被删除。除非您明确删除它。

答案 1 :(得分:0)

尝试将类Student的声明中的函数QString name() const的声明移到Q_PROPERTY宏之前。或者在名称功能之前再次指定“public:”。宏正在将访问说明符重置为“private”。