访问作为signal参数传递给CML的C ++对象的属性

时间:2015-12-13 19:46:53

标签: c++ qt signals qml

我的目标是将自定义C ++类“Contact”的实例作为从C ++类“ContactHelper”发出的信号“contactFound”的参数“contact”传递给QML;并在QML中的“onContactFound”信号处理程序中访问信号参数“contact”的属性。

从QML方面来看,对象“contact”基本上是一个数据结构,有2个只读属性,没有方法。

我尝试了两种方法,这两种方法都在本问题底部的示例代码中显示。 编辑:在此问题的原始版本中,均未奏效。感谢@BaCaRoZzo的评论,方法1现在有效(从而解决了我的直接问题)。

方法1)“联系人”以QT documentation中的自定义类型示例“阻止”和“消息”为模型。即“Contact”是通过 qRegisterMetaType 声明的,并且不是基于 QObject ,而是使用 Q_GADGET 宏(来自BaCaRoZzo的输入)。

这种方法既可以通过引用(& contact)和值(contact)传递给信号,但是当通过指针/地址(* contact)传递时会失败。

方法2)“Contact2”基于 QObject ,通过 qmlRegisterType 声明,并通过指针/地址(* contact2)传递。

代码编译并运行,但这两种方法都没有给我预期的信号参数属性访问。

方法1)在QML中,“onContactFound”的参数“contact”有效,但联系人的属性未定义。 编辑:通过将缺少的 Q_GADGET 宏添加到contact.h来解决此问题。

在QML中

方法2)未定义“onContactFound2”的参数“contact”!

编辑:鉴于方法1现在有效,我可以在我的实际代码中使用它,并略微改变这个问题的重点,即:

a)什么阻止方法2(对象/ qmlRegisterType /由指针*传递)?

b)假设两种方法都可以工作,哪种方法最适合通过C ++到QML的信号参数传输轻量级只读数据结构(少数字符串属性+ 1字符串数组属性)?

我正在使用Qt5.5.1开发,以Android 6.0.1设备为目标。

下面的示例代码可以粘贴到新的“QtQuick Controls Application”项目中。

的main.cpp

#include <QApplication>
#include <QQmlApplicationEngine>
#include <QtQml>
#include "contactshelper.h"
#include "contact.h"
#include "contact2.h"
int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    qmlRegisterType<ContactsHelper>("ContactsHelper",1,0,"ContactsHelper");
    qRegisterMetaType<Contact>();
    qmlRegisterType<Contact2>("ContactsHelper",1,0,"Contact");
    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    return app.exec();
}

contact.h

#ifndef CONTACT_H
#define CONTACT_H
#include <QDebug>
#include <QMetaType>
class Contact {
    Q_GADGET //!!!This macro was missing in the original question!!!
public:
    Contact();
    Contact(const Contact &other);
    ~Contact();
    Q_PROPERTY(QString contactId MEMBER m_contactId)
    Q_PROPERTY(QString displayLabel MEMBER m_displayLabel)
    void setContactId(const QString contactId);
    void setDisplayLabel(const QString displayLabel);
private:
    QString m_contactId;
    QString m_displayLabel;
};
Q_DECLARE_METATYPE(Contact)
#endif // CONTACT_H

contact.cpp

#include "contact.h"
#include <QDebug>
Contact::Contact(){}
Contact::~Contact(){}
Contact::Contact(const Contact &other) {
    qDebug() << "Contact: copy constructor called: " << other.m_displayLabel;
    m_contactId = other.m_contactId;
    m_displayLabel = other.m_displayLabel;
}
void Contact::setContactId(const QString contactId) {
    m_contactId = contactId;
}
void Contact::setDisplayLabel(const QString displayLabel) {
    m_displayLabel = displayLabel;
}

contact2.h

#ifndef CONTACT2_H
#define CONTACT2_H
#include <QDebug>
#include <QObject>
class Contact2: public QObject
{
    Q_OBJECT
public:
    explicit Contact2(QObject *parent = 0);
    ~Contact2();
    Q_PROPERTY(QString contactId MEMBER m_contactId)
    Q_PROPERTY(QString displayLabel MEMBER m_displayLabel)
    void setContactId(const QString contactId);
    void setDisplayLabel(const QString displayLabel);
private:
    QString m_contactId;
    QString m_displayLabel;
};
#endif // CONTACT2_H

contact2.cpp

#include "contact2.h"
Contact2::Contact2(QObject *parent) : QObject(parent) {}
Contact2::~Contact2() {}
void Contact2::setContactId(const QString contactId) {
    m_contactId = contactId;
}
void Contact2::setDisplayLabel(const QString displayLabel) {
    m_displayLabel = displayLabel;
}

contactshelper.h

#ifndef CONTACTSHELPER_H
#define CONTACTSHELPER_H
#include "contact.h"
#include "contact2.h"
#include <QObject>
class ContactsHelper : public QObject {
    Q_OBJECT
public:
    explicit ContactsHelper(QObject *parent = 0);
    Q_INVOKABLE void fakeContactFound();
    Q_INVOKABLE void fakeContactFound2();
signals:
    void contactFound(const int index, const int count, const Contact &contact);
    void contactFound2(const int index, const int count, const Contact *contact);
};
#endif // CONTACTSHELPER_H

contactshelper.cpp

#include "contactshelper.h"
#include "contact.h"
ContactsHelper::ContactsHelper(QObject *parent) : QObject(parent) {}
void ContactsHelper::fakeContactFound() {
    qDebug() << "ContactsHelper: faking contactFound";
    Contact contact;
    contact.setContactId("123");
    contact.setDisplayLabel("Aunt Agatha");
    contactFound(1, 1, contact);
}
void ContactsHelper::fakeContactFound2() {
    qDebug() << "ContactsHelper: faking contactFound";
    Contact2 *contact  = new Contact2;
    contact->setContactId("123");
    contact->setDisplayLabel("Uncle Fred");
    this->contactFound2(1, 1, contact);
}

main.qml

import QtQuick 2.5
import QtQuick.Controls 1.4
import ContactsHelper 1.0
ApplicationWindow {
    visible: true
    ContactsHelper {
        id: contactsHelper
        onContactFound: {
            console.log ("QML: onContactFound signal received!");
            console.log ("QML: displayLabel: " + contact.displayLabel);
            listProperty(contact);
        }
        onContactFound2: {
            console.log ("QML: onContactFound2 signal received!");
            console.log ("QML: displayLabel: " + contact.displayLabel);
            listProperty(contact);
        }
        function listProperty(item) {
            console.log ("QML: listing contact properties ...");
            for (var p in item)
                console.log(p + ": " + item[p]);
        }
    }
    MainForm {
        anchors.fill: parent
        button1.onClicked: {contactsHelper.fakeContactFound()}
        button2.onClicked: {contactsHelper.fakeContactFound2()}
    }
}

MainForm.ui.qml

import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.2
Item {
    width: 640
    height: 480
    property alias button1: button1
    property alias button2: button2
    RowLayout {
        anchors.centerIn: parent
        Button {
            id: button1
            text: qsTr("Fake contactFound")
        }
        Button {
            id: button2
            text: qsTr("Fake contactFound2")
        }
    }
}

0 个答案:

没有答案