本篇主要介绍 QQmlListProperty 类的使用, 通过 QQmlListProperty 类实现 QML 与 C++ 类的交互。
本篇以官方示例 properties 为例,重点内容如下:
首先使用 Q_PROPERTY 注册 guests 属性,guests 是一个数组
class BirthdayParty : public QObject
{
Q_OBJECT
Q_PROPERTY(QQmlListProperty guests READ guests)
public:
QQmlListProperty guests() ;
void appendGuest(Person *guest);
int guestCount() const;
Person *guestAt(int idx) const;
void clearGuests();
private:
static void appendGuest(QQmlListProperty *, Person *guest);
static int guestCount(QQmlListProperty *);
static Person *guestAt(QQmlListProperty *,int idx);
static void clearGuests(QQmlListProperty *);
private:
QVector m_guests;
};
从上面的代码中可以看到,BirthdayParty 类中还有许多成员函数,这些函数主要是提供给 QQmlListProperty 回调的,QQmlListProperty 构造函数声明如下:
QQmlListProperty(QObject *object, QList &list) // 1
QQmlListProperty(QObject *object, void *data, AppendFunction append, CountFunction count, AtFunction at, ClearFunction clear) //2
QQmlListProperty(QObject *object, void *data, CountFunction count, AtFunction at) // 3
第一个构造函数最简单,但由于我们在 BirthdayParty 中声明的是
QVector m_guests;
如果是 QList
第二个和第三个不同点:第三个是只读的。我们使用的是第二个构造函数,使用方法如下:
QQmlListProperty BirthdayParty::guests()
{
return QQmlListProperty(this, this,
&BirthdayParty::appendGuest,
&BirthdayParty::guestCount,
&BirthdayParty::guestAt,
&BirthdayParty::clearGuests);
}
void BirthdayParty::setHost(Person *host)
{
m_host = host;
}
void BirthdayParty::appendGuest(Person *guest)
{
m_guests.append(guest);
}
int BirthdayParty::guestCount() const
{
return m_guests.count();
}
Person *BirthdayParty::guestAt(int idx) const
{
return m_guests.at(idx);
}
void BirthdayParty::clearGuests()
{
m_guests.clear();
}
void BirthdayParty::appendGuest(QQmlListProperty *list, Person *guest)
{
reinterpret_cast(list->data)->appendGuest(guest);
}
int BirthdayParty::guestCount(QQmlListProperty *list)
{
return reinterpret_cast(list->data)->guestCount();
}
Person *BirthdayParty::guestAt(QQmlListProperty *list,int idx)
{
return reinterpret_cast(list->data)->guestAt(idx);
}
void BirthdayParty::clearGuests(QQmlListProperty *list)
{
reinterpret_cast(list->data)->clearGuests();
}
完整的程序代码如下:
// pro 文件
QT += core qml
HEADERS += \
BirthdayParty.h \
Person.h
SOURCES += \
BirthdayParty.cpp \
Person.cpp \
main.cpp
RESOURCES += \
resource.qrc
// Person.h
#ifndef PERSON_H
#define PERSON_H
#include
class Person : public QObject
{
Q_OBJECT
Q_PROPERTY(QString name READ name WRITE setName)
Q_PROPERTY(int shoeSize READ shoeSize WRITE setShoeSize)
public:
explicit Person(QObject *parent = nullptr);
QString name() const;
int shoeSize() const;
signals:
public slots:
void setName(QString name);
void setShoeSize(int shoeSize);
private:
QString m_name;
int m_shoeSize;
};
#endif // PERSON_H
// Person.cpp
#include "Person.h"
Person::Person(QObject *parent) : QObject(parent)
{
}
QString Person::name() const
{
return m_name;
}
int Person::shoeSize() const
{
return m_shoeSize;
}
void Person::setName(QString name)
{
m_name = name;
}
void Person::setShoeSize(int shoeSize)
{
m_shoeSize = shoeSize;
}
// Birthday.h
#ifndef BIRTHDAYPARTY_H
#define BIRTHDAYPARTY_H
#include
#include
#include
#include "Person.h"
class BirthdayParty : public QObject
{
Q_OBJECT
Q_PROPERTY(Person* host READ host WRITE setHost)
Q_PROPERTY(QQmlListProperty guests READ guests)
public:
explicit BirthdayParty(QObject *parent = nullptr);
Person* host() const;
QQmlListProperty guests() ;
void appendGuest(Person *guest);
int guestCount() const;
Person *guestAt(int idx) const;
void clearGuests();
signals:
public slots:
void setHost(Person* host);
private:
static void appendGuest(QQmlListProperty *, Person *guest);
static int guestCount(QQmlListProperty *);
static Person *guestAt(QQmlListProperty *,int idx);
static void clearGuests(QQmlListProperty *);
private:
Person* m_host;
QVector m_guests;
};
#endif // BIRTHDAYPARTY_H
// BirthdayParty.cpp
#include "BirthdayParty.h"
BirthdayParty::BirthdayParty(QObject *parent) : QObject(parent)
{
}
Person *BirthdayParty::host() const
{
return m_host;
}
QQmlListProperty BirthdayParty::guests()
{
return QQmlListProperty(this, this,
&BirthdayParty::appendGuest,
&BirthdayParty::guestCount,
&BirthdayParty::guestAt,
&BirthdayParty::clearGuests);
}
void BirthdayParty::setHost(Person *host)
{
m_host = host;
}
void BirthdayParty::appendGuest(Person *guest)
{
m_guests.append(guest);
}
int BirthdayParty::guestCount() const
{
return m_guests.count();
}
Person *BirthdayParty::guestAt(int idx) const
{
return m_guests.at(idx);
}
void BirthdayParty::clearGuests()
{
m_guests.clear();
}
void BirthdayParty::appendGuest(QQmlListProperty *list, Person *guest)
{
reinterpret_cast(list->data)->appendGuest(guest);
}
int BirthdayParty::guestCount(QQmlListProperty *list)
{
return reinterpret_cast(list->data)->guestCount();
}
Person *BirthdayParty::guestAt(QQmlListProperty *list,int idx)
{
return reinterpret_cast(list->data)->guestAt(idx);
}
void BirthdayParty::clearGuests(QQmlListProperty *list)
{
reinterpret_cast(list->data)->clearGuests();
}
// main.cpp
#include
#include
#include
#include
#include "Person.h"
#include "BirthdayParty.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
qmlRegisterType("People", 1, 0, "BirthdayParty");
qmlRegisterType("People", 1, 0, "Person");
QQmlEngine engine;
QQmlComponent component(&engine, QUrl("qrc:example.qml"));
BirthdayParty *party = qobject_cast(component.create());
if(party && party->host())
{
qDebug() << party->host()->name() << "has a birthday party";
qDebug() << "he is inviting:";
for(int i = 0; i < party->guestCount(); i++)
{
qDebug()<< "\t" << party->guestAt(i)->name();
}
}
else
{
qCritical() << component.errorString();
}
return 0;
}
// example.qml
import People 1.0
// ![0]
BirthdayParty {
host: Person {
name: "Bob Jones"
shoeSize: 12
}
guests: [
Person { name: "Leo Hodges" },
Person { name: "Jack Smith" },
Person { name: "Anne Brown" }
]
}
程序运行结果:
"Bob Jones" has a birthday party
he is inviting:
"Leo Hodges"
"Jack Smith"
"Anne Brown"