QML入门之 QML访问 C++类中的数组 (三)

    本篇主要介绍 QQmlListProperty 类的使用, 通过 QQmlListProperty  类实现 QML 与 C++ 类的交互。

    本篇以官方示例 properties 为例,重点内容如下:

    首先使用 Q_PROPERTY 注册 guests 属性,guests 是一个数组

class BirthdayParty : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QQmlListProperty<Person> guests READ guests)

public:
    QQmlListProperty<Person> guests() ;

    void appendGuest(Person *guest);
    int guestCount() const;
    Person *guestAt(int idx) const;
    void clearGuests();

private:
    static void appendGuest(QQmlListProperty<Person> *, Person *guest);
    static int guestCount(QQmlListProperty<Person> *);
    static Person *guestAt(QQmlListProperty<Person> *,int idx);
    static void clearGuests(QQmlListProperty<Person> *);

private:
    QVector<Person *> m_guests;
};
    从上面的代码中可以看到,BirthdayParty 类中还有许多成员函数,这些函数主要是提供给 QQmlListProperty  回调的,QQmlListProperty  构造函数声明如下:
QQmlListProperty(QObject *object, QList<T *> &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<Person *> m_guests;

    如果是 QList<T *>类型,我们可以使用第一个构造,在上一篇中我们就使用了第一个构造函数。

    第二个和第三个不同点:第三个是只读的。我们使用的是第二个构造函数,使用方法如下:

QQmlListProperty<Person> BirthdayParty::guests()
{
    return QQmlListProperty<Person>(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<Person> *list, Person *guest)
{
    reinterpret_cast<BirthdayParty *>(list->data)->appendGuest(guest);
}

int BirthdayParty::guestCount(QQmlListProperty<Person> *list)
{
    return reinterpret_cast<BirthdayParty *>(list->data)->guestCount();
}

Person *BirthdayParty::guestAt(QQmlListProperty<Person> *list,int idx)
{
    return reinterpret_cast<BirthdayParty *>(list->data)->guestAt(idx);
}

void BirthdayParty::clearGuests(QQmlListProperty<Person> *list)
{
    reinterpret_cast<BirthdayParty *>(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 <QObject>

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 <QObject>
#include <QQmlListProperty>
#include <QVector>

#include "Person.h"

class BirthdayParty : public QObject
{
    Q_OBJECT
    Q_PROPERTY(Person* host READ host WRITE setHost)
    Q_PROPERTY(QQmlListProperty<Person> guests READ guests)


public:
    explicit BirthdayParty(QObject *parent = nullptr);

    Person* host() const;

    QQmlListProperty<Person> 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> *, Person *guest);
    static int guestCount(QQmlListProperty<Person> *);
    static Person *guestAt(QQmlListProperty<Person> *,int idx);
    static void clearGuests(QQmlListProperty<Person> *);

private:
    Person* m_host;

    QVector<Person *> m_guests;
};

#endif // BIRTHDAYPARTY_H


// BirthdayParty.cpp
#include "BirthdayParty.h"

BirthdayParty::BirthdayParty(QObject *parent) : QObject(parent)
{

}

Person *BirthdayParty::host() const
{
    return m_host;
}

QQmlListProperty<Person> BirthdayParty::guests()
{
    return QQmlListProperty<Person>(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<Person> *list, Person *guest)
{
    reinterpret_cast<BirthdayParty *>(list->data)->appendGuest(guest);
}

int BirthdayParty::guestCount(QQmlListProperty<Person> *list)
{
    return reinterpret_cast<BirthdayParty *>(list->data)->guestCount();
}

Person *BirthdayParty::guestAt(QQmlListProperty<Person> *list,int idx)
{
    return reinterpret_cast<BirthdayParty *>(list->data)->guestAt(idx);
}

void BirthdayParty::clearGuests(QQmlListProperty<Person> *list)
{
    reinterpret_cast<BirthdayParty *>(list->data)->clearGuests();
}


// main.cpp
#include <QCoreApplication>
#include <QQmlEngine>
#include <QQmlComponent>
#include <QDebug>

#include "Person.h"
#include "BirthdayParty.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    qmlRegisterType<BirthdayParty>("People", 1, 0, "BirthdayParty");
    qmlRegisterType<Person>("People", 1, 0, "Person");

    QQmlEngine engine;
    QQmlComponent component(&engine, QUrl("qrc:example.qml"));

    BirthdayParty *party = qobject_cast<BirthdayParty *>(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"






    

<think>好的,我需要帮助用户了解如何入门C++ Qt开发以及相关的项目实战案例。首先,用户已经提供了个引用资源,我需要结合这些信息来组织回答。 首先,用户提到的引用[1]提到课程分为入门、进阶和企业级项目实战,以及开源项目学习。引用[2]和[3]分别涉及五子棋游戏项目和QtQuick/QML的内容。我需要将这些内容整合成一个结构清晰的入门路径。 接下来,我应该分步骤介绍学习路径。第一步通常是环境搭建,安装Qt Creator和配置编译器。第二步是学习C++基础,特别是Qt相关的部分,比如面向对象编程。第步是Qt框架的基础知识,比如信号与槽机制、界面设计等。然后可以介绍项目实战,比如引用中的五子棋游戏,以及QML的学习路径。 另外,用户要求生成相关问题,我需要考虑初学者可能遇到的疑问,比如学习资源、项目选择、跨平台开发等。同时,需要确保回答中正确引用提供的参考资料,例如在提到项目实战时引用[2]和[3]。 还要注意使用中文,并按照系统指令使用正确的LaTeX格式,虽然这个回答可能涉及较少的数学公式,但如果有变量或代码示例,要正确应用格式。例如,代码块需要用```python或```cpp标注,但根据用户示例,可能更倾向于使用Python,不过这里应该用C++代码示例。 需要检查是否有遗漏的步骤,比如答疑服务、学习资料等,这些在引用中都有提到,应该在回答中强调这些资源的可用性,帮助用户了解支持服务。 最后,确保回答结构清晰,分点明确,帮助用户逐步从入门到实战,同时自然插入引用标注。例如,在提到课程时添加[^1],项目实战时引用[^2],QML部分引用[^3]。</think>### C++ Qt开发入门与项目实战指南 #### 一、学习路径与核心知识点 1. **环境搭建** - 安装Qt Creator(跨平台IDE)和配置C++编译器(MSVC/GCC) - 创建第一个Qt Widgets项目,理解`.pro`文件结构 - 示例代码: ```cpp #include <QApplication> #include <QLabel> int main(int argc, char *argv[]) { QApplication app(argc, argv); QLabel label("Hello Qt!"); label.show(); return app.exec(); } ``` 2. **C++基础强化** - 重点掌握:面向对象特性、智能指针、Lambda表达式 - Qt特有扩展:`QString`字符串处理、`QList`容器 3. **Qt框架核心机制** - 信号与槽通信:`connect(sender, SIGNAL(), receiver, SLOT())` - 界面设计:使用Qt Designer创建`.ui`文件,布局管理(QVBoxLayout/QHBoxLayout) - 事件处理:重写`mousePressEvent()`等虚函数 #### 二、项目实战案例推荐 1. **五子棋游戏开发** - 核心实现: - 棋盘绘制:重写`paintEvent()`方法 - 胜负判定算法:使用二维数组存储棋局状态 - 网络对战模块:QTcpSocket实现双人对战 2. **企业级应用开发** - 数据库应用:使用QSql模块连接MySQL/SQLite - 跨平台文件操作:`QFile`和`QDir` - 多线程编程:`QThread`与`QtConcurrent`框架 3. **QML现代界面开发**[^3] - 声明式UI开发:实现动态效果和3D界面 - 与C++混合编程:暴露C++对象给QML使用 - 示例结构: ```qml ApplicationWindow { visible: true Button { text: "点击" onClicked: console.log("Qt Quick按钮点击") } } ``` #### 、推荐学习资源 1. **系统化学习路径** - 阶段1:Qt Widgets基础(2-4周) - 阶段2:高级功能(网络/数据库/多线程,3-5周) - 阶段3:QML现代界面开发(2-3周) 2. **实战训练建议** - 每日编码练习:从对话框工具到完整管理系统 - 开源项目学习:分析Qt官方示例(如:QT Charts示例) 3. **进阶技能拓展** - 性能优化:内存管理、渲染加速 - 跨平台部署:Windows/Linux/macOS打包技巧 - 第方库集成:OpenCV图像处理、QuickChart数据可视化
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值