在插槽中接收C ++对象

时间:2015-03-04 07:53:20

标签: qt qml qt5 qtquick2

我想通过signal-slot发送一个C ++对象到QML:

class TaskInfo : public QObject
{
    Q_OBJECT

    Q_PROPERTY(QString name READ taskName)
    ...

// constructors
public:
    TaskInfo();
    TaskInfo(QIODevice *in);
    TaskInfo(TaskInfo &&taskInfo);
    TaskInfo(const TaskInfo &taskInfo); // it's just copy all variable
    ...
}

我有一个类将TaskInfo对象发送到QML:

class DLDataConverter : public QObject
{
    Q_OBJECT

signals:
    void taskAdded_testQML(const TaskInfo taskInfo);
    void taskAdded_useQString(const QString taskInfo);
    ...
}

我也发出信号并用QML接收:

void DLDataConverter::addItem(const TaskInfo &taskInfo)
{
    emit taskAdded_testQML(taskInfo);
    emit taskAdded_useQString(taskInfo.getInfoToString());
}

QML代码:

Connections {
    target: DLDataConverter

    onTaskAdded_testQML: {
        console.log(taskInfo);
    }

    onTaskAdded_useQString: {
        console.log(taskInfo);
    }
}

onTaskAdded_useQString信号工作正常,但onTaskAdded_testQML打印'undefined'。

我已经注册了这些类型:

qmlRegisterType<TaskInfo>("taskInfo", 1, 0, "TaskInfo"); qmlRegisterSingletonType<DLDataConverter>("Singleton.DLDataConverter", 1, 0, "DLDataConverter", dataObj);

我可以创建TaskInfo对象并且效果很好:

TaskInfo{
    id: t
}


Connections {
    target: DLDataConverter

    onTaskAdded_testQML: {
        console.log(t.name);  // print default value, is "Noname"
        console.log(taskInfo);  // print 'undefined'
    }
}

1 个答案:

答案 0 :(得分:3)

QML使用来自Qt的数据,将每个参数转换为QVariant,然后,如果可能,将其转换为本机JavaScript值。如果它们无法转换为JS,您仍然可以使用JS复制并传递它们,但您无法使用它们。在不扩展QVariant的情况下,只有QObject*可以保存在QVariant中,并且JS是线程,它的属性,槽和信号对JS是可见的。任何指向对象的指针(其类派生自QObject)都会被QObject*隐式转换为QVariant。因此,您可以自由地定义指向您的类的指针的信号:

class DLDataConverter : public QObject
{
    Q_OBJECT

signals:
    void taskAdded_testQML(TaskInfo *taskInfo);
    void taskAdded_useQString(const QString taskInfo);
    ...
}

指针介绍了对象生命周期的问题,因此您一定要详细了解如何manage the ownership of objects。 如果你在Qml中创建你的对象:

TaskInfo{
    id: t
}

您创建的对象具有parent,其生命周期决定了对象本身的生命周期。指针绑定到本地QML上下文中的名称t