百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

Qt C++属性类型提供给 QML调用(三)

bigegpt 2024-08-22 10:50 5 浏览

前言

前面两篇文章已经介绍了 QML 中如何调用 C++中的基础属性以及对象属性,今天继续来介绍另外一种:对象为列表类型的属性调用方法。

概述

包含QObject派生类型列表的属性也可以暴露给QML使用,但是,应该使用QQmlListProperty类而不是QList< T >作为属性类型。这是因为QList不是QObject派生的类型,所以不能通过Qt元对象系统提供必要的QML属性特性,例如,当列表被修改时的信号通知,这就需要调用对象为列表类型的属性。

QQmlListProperty是一个模板类,可以通过QList值方便地构建。

正文

我们继续在之前的工程中进行修改,新建一个 School 类,示例如下:

//school.h
#include <QQmlListProperty>
#include <QObject>
#include <QDebug>
#include "student.h"

class School : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QQmlListProperty<Student> students READ students)

public:

    explicit School(QObject * parent = 0);
    QQmlListProperty<Student> students();
    void appendStudent(Student * stu);
    int studentCount() const;
    Student *student(int) const;
    void clearStudent();

private:
    static void appendStudent(QQmlListProperty<Student> *list, Student * s);
    static int studentCount(QQmlListProperty<Student>*);
    static Student* student(QQmlListProperty<Student>*, int);
    static void clearStudent(QQmlListProperty<Student>*);


private:
    QList<Student *> m_students;
};

//school.cpp
School::School(QObject *parent) : QObject(parent)
{

}

QQmlListProperty<Student> School::students()
{
    return QQmlListProperty<Student>(this,this,
                                     &School::appendStudent,
                                     &School::studentCount,
                                     &School::student,
                                     &School::clearStudent);
}

void School::appendStudent(Student *stu)
{
    m_students.append(stu);
}

int School::studentCount() const
{
    return m_students.count();
}

Student *School::student(int index) const
{
    return m_students.at(index);
}

void School::clearStudent()
{
    return m_students.clear();
}

void School::appendStudent(QQmlListProperty<Student> *list, Student *s)
{
    reinterpret_cast< School* >(list->data)->appendStudent(s);
}

int School::studentCount(QQmlListProperty<Student> *list)
{
    return reinterpret_cast< School* >(list->data)->studentCount();
}

Student *School::student(QQmlListProperty<Student> *list, int i)
{
    return reinterpret_cast< School* >(list->data)->student(i);
}

void School::clearStudent(QQmlListProperty<Student> *list)
{
    reinterpret_cast< School* >(list->data)->clearStudent();
}

School 里面提供了一个students列表,并注册成QQmlListProperty类型供 QML 调用。

然后 Student 类保持不变:

class Student : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QString name READ getName WRITE setName NOTIFY sigNameChanged)


public:
    explicit Student(QObject *parent = nullptr);
    ~Student(){}


    void setName(const QString & name){
        if(name != m_name){
            m_name = name;
            emit sigNameChanged(m_name);
        }
    }
    QString getName() const {return m_name;}
signals:
    void sigNameChanged(QString name);


private:
    QString

在 Main 函数中对类进行注册:

qmlRegisterType<Student>("Student", 1, 0, "Student");
qmlRegisterType<School>("School", 1, 0, "School");

然后在 QML 中进行调用:

import QtQuick 2.8
import Student 1.0
import School 1.0

School{
    students:[
        Student{name:"xiaoming"},
        Student{name:"zhangsan"},
        Student{name:"lisi"}
    ]
}

这里定义了一个School类型,其中包含三个 Student,每个 Student 设置其名称。

然后我们回到 main 函数中 将 qml 定义好的对象打印出来看看效果:

QQmlEngine engine;
QQmlComponent component(&engine, QUrl("qrc:main.qml"));
School *school = qobject_cast<School *>(component.create());

if(school){
   for (int i = 0; i < school->studentCount(); ++i)
      qWarning() << "   " << school->student(i)->getName();
}

运行程序,输出如下:

"xiaoming"
"zhangsan"
"lisi"

本文中是试验从 QML 中创建列表对象,然后在C++中打印出创建好的列表,当然也可以在 C++中创建好列表,然后在 QML 中进行调用。使用方法都是一样,这里就不再赘述。

需要注意的是,在 Qt 帮助文档中,QQmlListProperty的使用方法如下:

class MessageBoard : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QQmlListProperty<Message> messages READ messages)
public:
    QQmlListProperty<Message> messages();

private:
    static void append_message(QQmlListProperty<Message> *list, Message *msg);

    QList<Message *> m_messages;
};

QQmlListProperty<Message> MessageBoard::messages()
{
    return QQmlListProperty<Message>(this, 0, &MessageBoard::append_message);
}

void MessageBoard::append_message(QQmlListProperty<Message> *list, Message *msg)
{
    MessageBoard *msgBoard = qobject_cast<MessageBoard *>(list->object);
    if (msg)
        msgBoard->m_messages.append(msg);
}

这里添加列表元素的时候只用到了一个静态函数append_message,奇怪的是我用这种方法一直会报错,编译不通过,无奈之下用了第二种方法,将所有需要的静态函数全部写进去了。其实该类的构造函数有三个,如下:

QQmlListProperty::QQmlListProperty(QObject *object, QList<T *> &list)
QQmlListProperty::QQmlListProperty(QObject *object, void *data, AppendFunction append, CountFunction count, AtFunction at, ClearFunction clear)
QQmlListProperty::QQmlListProperty(QObject *object, void *data, CountFunction count, AtFunction at)

我用第一个构造函数的方式一直报错,然而使用所有参数的形式就正常,目前还不知道是什么原因,先这样吧。

【领QT开发教程学习资料,点击下方链接莬费领取↓↓,先码住不迷路~】

点击这里:「链接」

相关推荐

悠悠万事,吃饭为大(悠悠万事吃饭为大,什么意思)

新媒体编辑:杜岷赵蕾初审:程秀娟审核:汤小俊审签:周星...

高铁扒门事件升级版!婚宴上‘冲喜’老人团:我们抢的是社会资源

凌晨两点改方案时,突然收到婚庆团队发来的视频——胶东某酒店宴会厅,三个穿大红棉袄的中年妇女跟敢死队似的往前冲,眼瞅着就要扑到新娘的高额钻石项链上。要不是门口小伙及时阻拦,这婚礼造型团队熬了三个月的方案...

微服务架构实战:商家管理后台与sso设计,SSO客户端设计

SSO客户端设计下面通过模块merchant-security对SSO客户端安全认证部分的实现进行封装,以便各个接入SSO的客户端应用进行引用。安全认证的项目管理配置SSO客户端安全认证的项目管理使...

还在为 Spring Boot 配置类加载机制困惑?一文为你彻底解惑

在当今微服务架构盛行、项目复杂度不断攀升的开发环境下,SpringBoot作为Java后端开发的主流框架,无疑是我们手中的得力武器。然而,当我们在享受其自动配置带来的便捷时,是否曾被配置类加载...

Seata源码—6.Seata AT模式的数据源代理二

大纲1.Seata的Resource资源接口源码2.Seata数据源连接池代理的实现源码3.Client向Server发起注册RM的源码4.Client向Server注册RM时的交互源码5.数据源连接...

30分钟了解K8S(30分钟了解微积分)

微服务演进方向o面向分布式设计(Distribution):容器、微服务、API驱动的开发;o面向配置设计(Configuration):一个镜像,多个环境配置;o面向韧性设计(Resista...

SpringBoot条件化配置(@Conditional)全面解析与实战指南

一、条件化配置基础概念1.1什么是条件化配置条件化配置是Spring框架提供的一种基于特定条件来决定是否注册Bean或加载配置的机制。在SpringBoot中,这一机制通过@Conditional...

一招解决所有依赖冲突(克服依赖)

背景介绍最近遇到了这样一个问题,我们有一个jar包common-tool,作为基础工具包,被各个项目在引用。突然某一天发现日志很多报错。一看是NoSuchMethodError,意思是Dis...

你读过Mybatis的源码?说说它用到了几种设计模式

学习设计模式时,很多人都有类似的困扰——明明概念背得滚瓜烂熟,一到写代码就完全想不起来怎么用。就像学了一堆游泳技巧,却从没下过水实践,很难真正掌握。其实理解一个知识点,就像看立体模型,单角度观察总...

golang对接阿里云私有Bucket上传图片、授权访问图片

1、为什么要设置私有bucket公共读写:互联网上任何用户都可以对该Bucket内的文件进行访问,并且向该Bucket写入数据。这有可能造成您数据的外泄以及费用激增,若被人恶意写入违法信息还可...

spring中的资源的加载(spring加载原理)

最近在网上看到有人问@ContextConfiguration("classpath:/bean.xml")中除了classpath这种还有其他的写法么,看他的意思是想从本地文件...

Android资源使用(android资源文件)

Android资源管理机制在Android的开发中,需要使用到各式各样的资源,这些资源往往是一些静态资源,比如位图,颜色,布局定义,用户界面使用到的字符串,动画等。这些资源统统放在项目的res/独立子...

如何深度理解mybatis?(如何深度理解康乐服务质量管理的5个维度)

深度自定义mybatis回顾mybatis的操作的核心步骤编写核心类SqlSessionFacotryBuild进行解析配置文件深度分析解析SqlSessionFacotryBuild干的核心工作编写...

@Autowired与@Resource原理知识点详解

springIOCAOP的不多做赘述了,说下IOC:SpringIOC解决的是对象管理和对象依赖的问题,IOC容器可以理解为一个对象工厂,我们都把该对象交给工厂,工厂管理这些对象的创建以及依赖关系...

java的redis连接工具篇(java redis client)

在Java里,有不少用于连接Redis的工具,下面为你介绍一些主流的工具及其特点:JedisJedis是Redis官方推荐的Java连接工具,它提供了全面的Redis命令支持,且...