2017.5.8 更新:Record类要用指针,QObject 不能有拷贝函数。

我有一个C++中自定义的ReaderModel,继承自QAbstractListModel类,传递给了QML。

它的me成员是一个Reader指针,Reader有个成员是RecordModel。

通过reader获取的recordModel,在qml中类型是QVariant(RecordModel),我没法把它作为一个ListView的model。

要怎么让它绑定给view呢?

我尝试者把数据拷贝到一个直接传给qml的recordModel,但是当数据之后发生了变化时,视图就不会更新,除非再次拷贝,这样效率不可观。

通过艰难地google查找相关问题,我最后的解决方案是:

取消这个RecordModel成员,用QVariantList来储存所有record。

简单地说就是传递自定义类中的自定义结构体数组。

作为解决方案的代码(如果不需要,完全可以不用ReaderModel,但是要用setContextProperty把reader变量传给qml):

record.h

#ifndef RECORD_H

#define RECORD_H

#include

class Record: public QObject

{

Q_OBJECT

Q_PROPERTY(QString bookId READ bookId WRITE setBookId NOTIFY bookIdChanged)

Q_PROPERTY(int state READ state WRITE setState NOTIFY stateChanged)

public:

Record(const QString &bookId="",int state=0):

bookId_(bookId),state_(state){}

Record(const Record &r){

bookId_ = r.bookId_;

state_ = r.state_;

}

QString bookId() const;

int state() const;

public slots:

void setBookId(const QString &);

void setState(int);

private:

QString bookId_;

int state_;

signals:

void bookIdChanged();

void stateChanged();

};

Q_DECLARE_METATYPE(Record*)//元类型注册

#endif // RECORD_H

reader.h

#ifndef READER_H

#define READER_H

#include

#include

class Reader: public QObject

{

Q_OBJECT

Q_PROPERTY(QString id READ id WRITE setId NOTIFY idChanged)

Q_PROPERTY(QString password READ password WRITE setPassword NOTIFY passwordChanged)

Q_PROPERTY(QVariantList record READ record WRITE setRecord NOTIFY recordChanged)

public:

Reader(const QString &id = "",

const QString &password = "")

: id_(id),password_(password){}

QString id() const; //id

QString password() const; //密码

QVariantList record() const; //记录

Q_INVOKABLE void doSomething()const;

public slots:

void setId(const QString &);

void setPassword(const QString &);

void setRecord(const QVariantList &);

private:

QString id_;

QString password_;

QVariantList record_;//借书记录

signals:

void idChanged();

void passwordChanged();

void recordChanged();

};

#endif // READER_H

readerModel.h

#ifndef READERMODEL_H

#define READERMODEL_H

#include

#include

#include

#include "reader.h"

#include "record.h"

class ReaderModel : public QAbstractListModel

{

Q_OBJECT

Q_PROPERTY(Reader* me READ me WRITE setMe NOTIFY meChanged)

public:

enum ReaderRole {

IdRole = Qt::DisplayRole, //0

PasswordRole = Qt::UserRole,

RecordRole

};

Q_ENUM(ReaderRole)

ReaderModel(QObject *parent = nullptr){Q_UNUSED(parent);}

int rowCount(const QModelIndex & = QModelIndex()) const;

QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;

QHash roleNames() const;

Q_INVOKABLE QVariantMap get(int row) const;

Q_INVOKABLE void append(const QString &id,

const QString &password);

Q_INVOKABLE void set(int row, const QString &id,

const QString &password);

Q_INVOKABLE void remove(int row);

Q_INVOKABLE Reader *me() const;//当前登录的用户对象指针

Q_INVOKABLE void setMe(Reader *r);

private:

QList m_readers;

Reader *me_;

signals:

void meChanged();

};

#endif // READERMODEL_H

reader.cpp

#include "reader.h"

#include "record.h"

#include

QString Reader::id() const

{

return id_;

}

QString Reader::password() const

{

return password_;

}

QVariantList Reader::record() const

{

return record_;

}

void Reader::setId(const QString &value)

{

if (id_ == value)

return;

id_ = value;

emit idChanged();

}

void Reader::setPassword(const QString &value)

{

if (password_ == value)

return;

password_ = value;

emit passwordChanged();

}

void Reader::setRecord(const QVariantList &value)

{

if (record_ == value)

return;

record_ = value;

emit recordChanged();

}

record.cpp

#include "record.h"

QString Record::bookId() const

{

return bookId_;

}

int Record::state() const

{

return state_;

}

void Record::setBookId(const QString &value)

{

if(bookId_ == value)

return;

bookId_ = value;

emit bookIdChanged();

}

void Record::setState(int value)

{

if(state_ == value)

return;

state_ = value;

emit stateChanged();

}

readerModel.cpp

#include "readermodel.h"

#include "reader.h"

int ReaderModel::rowCount(const QModelIndex & /*parent*/) const

{

return m_readers.count();

}

QVariant ReaderModel::data(const QModelIndex &index, int role) const

{

if(index.row() < rowCount())

switch(role){

case IdRole: return m_readers.at(index.row())->id();

case PasswordRole: return m_readers.at(index.row())->password();

case RecordRole: return m_readers.at(index.row())->record();

default: return QVariant();

}

return QVariant();

}

QHash ReaderModel::roleNames() const

{

static const QHash roles{

{IdRole, "id"},

{PasswordRole, "password"},

{RecordRole, "record"}

};

return roles;

}

QVariantMap ReaderModel::get(int row) const

{

Reader *reader = m_readers.value(row);

return { {"id", reader->id()},

{"password", reader->password()},

{"record", reader->record()}};

}

void ReaderModel::append(const QString &id, const QString &password)

{

int row = m_readers.count();

beginInsertRows(QModelIndex(), row, row);

Reader *r = new Reader(id, password, name, power, school, credit, money, unback);

m_readers.append(r);

endInsertRows();

}

void ReaderModel::set(int row, const QString &id, const QString &password)

{

if (row < 0 || row >= m_readers.count())

return;

Reader *r = new Reader(id, password == ""? m_readers[row]->password() : password);

m_readers.replace(row, r);

dataChanged(index(row, 0), index(row, 0), { IdRole,PasswordRole});

}

void ReaderModel::remove(int row)

{

if (row < 0 || row >= m_readers.count())

return;

beginRemoveRows(QModelIndex(), row, row);

m_readers.removeAt(row);

endRemoveRows();

}

Reader *ReaderModel::me() const

{

return me_;

}

void ReaderModel::setMe(Reader *r)

{

me_ = r;

emit meChanged();

}

main.cpp

#include

#include

#include

#include

#include "readermodel.h"

int main(int argc, char *argv[])

{

QGuiApplication app(argc, argv);

//向qml注册类型

qmlRegisterType("Backend", 1, 0, "ReaderModel");

ReaderModel *readerModel = new ReaderModel();

...//写入数据

QQmlApplicationEngine *engine = new QQmlApplicationEngine();

//向qml传递变量

engine->rootContext()->setContextProperty("readerModel", readerModel);

engine->load(QUrl(QLatin1String("qrc:/main.qml")));

return app.exec();

}

mail.qml:

ListView {

visible: true

id: recordView

width: parent.width

height: parent.height

model: readerModel.me.record

delegate:Rectangle{

property var record: readerModel.me.record[index]

RowLayout{

spacing: 10

Label {

text: record.bookId

}

Label {

text: record.state

}

}

Component.onCompleted: {

console.log(readerModel.me.record)

console.log("\n",readerModel.me.record[index])

console.log("\n",readerModel.me.record[index].state)

}

}

}

c++ qml 数组_【QML与C++混合编程】用QVariantList传递数组类型成员相关推荐

  1. C++与QML混合编程技术(传递自定义数据类型)

    目录 一.前言 二.C++与QML集成的基础 2.1 语言特征 2.2 可集成的前提条件 2.3 基础数据类型 2.4 自定义数据类型 三.实例讲解 3.1 QML获取C++类的自定义结构体数据 3. ...

  2. Java实现有序数组和无序数组_【算法】字典的诞生:有序数组 PK 无序链表

    参考资料 <算法(java)>                           - - Robert Sedgewick, Kevin Wayne <数据结构>       ...

  3. 多个数字数组_七个问题帮助初学者深入理解Java数组

    短文涨姿势,看了不白看,不关注等啥? 几乎所有的高级语言当中,都提供了一种叫做"数组"的东西,Java语言当然也不例外.我们通过数组可以很方便的存储和管理一组数据.因为在Java语 ...

  4. javascript字典中添加数组_如何在 JavaScript 中更好地使用数组

    在 freeCodeCamp 社区阅读原文. 本文短小精悍,我保证.在过去的数个月里,我注意到在我审阅的 pull request 中有四个(关于数组使用的)错误经常出现.同时,我自己也会犯这些错误, ...

  5. java控件数组_在C# WinForm程序中创建控件数组及相应的事件处理

    控件数组是VB提供的一个优秀的设计解决方案,它能很方便快捷的处理大批同类控件的响应和时间处理,但不知为什么在C#中这个优秀特性没有传承下来,甚为可惜,本文将要探讨就是如何在C# WinForm程序实现 ...

  6. java中将txt转换为数组_关于android:在Java中将列表转换为数组

    本问题已经有最佳答案,请猛点这里访问. 在Java中,如何将EDCOX1的0度转换为EDCOX1×1? 检查以下代码: ArrayList tiendas; List tiendasList; tie ...

  7. c++ 二维数组_【技术篇】C指针与二维数组深度辨析

    一.源代码 /*第01行*/ CLion 2019.3.4 x64中编写的源代码·截图 二.深度辨析 CLion 2019.3.4 x64中编译的结果·截图 zippo[4][2]是一个四行二列的in ...

  8. python 整除的数组_计算和可被整除的所有子数组

    在我学习面试的时候,我在GeeksForGeeks上找到了这个问题和解决方案,但不明白答案.在 上面说的是Let there be a subarray (i, j) whose sum is div ...

  9. scala 字符串转换数组_如何在Scala中将十六进制字符串转换为字节数组?

    scala 字符串转换数组 Hex String in Scala denotes value in hexadecimal number system i.e. base 16 number sys ...

最新文章

  1. 玩转正则之highlight高亮
  2. React Hooks - useEffect通俗易懂
  3. PYTHON调用JENKINS的API来进行CI
  4. wamp 安装monggo扩展
  5. htmlbuilder php phantomjs
  6. 转发- css(display,float,position)
  7. 判断手机是否输入表情
  8. c语言程序设计考试改革,C语言程序设计课程考试改革实施方案.pdf
  9. Linux SD卡驱动开发(四) —— SD 控制器之真正的硬件操作
  10. surfaceView和View区别
  11. 落户北京经开区 小米汽车首车预计2024年下线并量产 网友:开始存钱!
  12. linux打印全部make编译信息
  13. 计算机专业指南考试题6,计算机专业指南考试题.doc
  14. 选择尽可能多的不相交区间
  15. 函数的参数对象$event的使用和利用他找到事件对象
  16. Android开发-数据回传
  17. WinAPI双人贪吃蛇
  18. WinZip Pro 9 for Mac(专业zip压缩解压工具)
  19. 持续降库纯碱增仓大涨,沪铝认购小涨,螺纹10-01季节性正套2022.5.19
  20. 如何把桌面计算机和回收站隐藏,电脑回收站怎么隐藏图标,隐藏我的电脑和回收站...

热门文章

  1. Linux的目录说明
  2. kopernio显示无效程序_daz 无法渲染/没有渲染/渲染不显示/渲染无效?
  3. python管道pipe_Python multiprocessing模块中的Pipe管道
  4. 2021.01.04 第 1 个工作日反思
  5. 八数码宽度优先搜索python代码_图之遍历--广度优先遍历
  6. linux 设置时钟 教程,Linux hwclock命令参数及用法详解--Linux显示/设置硬件时钟命令...
  7. 【7】测试用例设计-等价类分析法
  8. python selenium 下拉框 页面变化_python-selenium之select下拉框
  9. 地磅称重软件源码_地磅称重软件需求梳理的重要性
  10. 颜色和心理年龄测试软件,超准的色彩心理学:选8个颜色,就可以测出你的心理年龄...