QML < 6 > C++ 向QML 传递复杂数据结构 TableView 使用C++ Model QAbstractTableModel
2021/12/8 1:17:32
本文主要是介绍QML < 6 > C++ 向QML 传递复杂数据结构 TableView 使用C++ Model QAbstractTableModel,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
QML < 6 > C++ 向QML 传递复杂数据结构 TableView 使用C++ Model QAbstractTableModel
前言
TableView 表格显示常用控件,使用C++ model 便于处理复杂的数据结构,也更利于数据和UI 解耦 ,
本文记录下 Tableview 使用C++ model示例,使用Model 为QAbstractTableModel。
表格数据和样式参照之前文章:QML <4> Tableview 自定义表格显示 delegate FontAwesome Canvas
一、QAbstractTableModel 类自定义 CustomDataModel
1数据格式
数据源JSON 数组格式,如下:
2数据结构定义
struct Music_Data { bool NewFlag; bool TrendUp; int TrendNum; QString ImageSouce; QString Title; int Time; QString Singer; }; QVector< Music_Data> vDatas;
3 数据结构字段对应枚举声明
Q_ENUMS(EM_DATA_ROLE) enum EM_DATA_ROLE { Data_Role_NewFlag = Qt::UserRole+1, Data_Role_TrendUp, Data_Role_TrendNum, Data_Role_ImageSouce, Data_Role_Title, Data_Role_Time, Data_Role_Singer };
4 重写rowCount
rowCount函数返回 表格行数,代码如下:
int CustomDataModel::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent); return vDatas.size(); }
5 重写columnCount
columnCount 函数返回表格列数,本文中表格列在QML 中TableView 定义,model 实现函数如下,
QStringlist head << QStringLiteral("")<< QStringLiteral("标题")<<QStringLiteral("时长")<< QStringLiteral("歌手"); int CustomDataModel::columnCount(const QModelIndex &parent) const { Q_UNUSED(parent); return head.size(); }
6 重写roleNames
roleNames 函数返回表格列role QML TableView 列定义相同Role ,根据Role 匹配获取表格单元格数据,代码如下:
QHash<int, QByteArray> CustomDataModel::roleNames() const { QHash<int, QByteArray> roles; roles[Data_Role_NewFlag] = "NewFlag"; roles[Data_Role_Title] = "Title"; roles[Data_Role_Time] = "Time"; roles[Data_Role_ImageSouce] = "ImageSouce"; roles[Data_Role_TrendNum] = "TrendNum"; roles[Data_Role_TrendUp] = "TrendUp"; roles[Data_Role_Singer] = "Singer"; return roles; }
7 重写data
QML TableView 更新但与个数据时调用data函数,根据Role 返回对应数据,代码如下:
QVariant CustomDataModel::data(const QModelIndex &index, int role) const { if(index.row() >= vDatas.size()) { return QVariant(); } const Music_Data rowData = vDatas.at(index.row()); switch(role) { case Data_Role_NewFlag: { return rowData.NewFlag; }break; case Data_Role_Time: { return rowData.Time; }break; case Data_Role_Title: { return rowData.Title; }break; case Data_Role_Singer: { return rowData.Singer; }break; case Data_Role_ImageSouce: { return rowData.ImageSouce; }break; case Data_Role_TrendNum: { return rowData.TrendNum; }break; case Data_Role_TrendUp: { return rowData.TrendUp; }break; default: return QVariant(); } }
8 定义自定义函数getDataFromRowByRole
getDataFromRowByRole 获取指定行指定列Role 数据,自定义函数要在QML 中调用 函数声明需要添加Q_INVOKABLE,代码如下:
Q_INVOKABLE QVariant getDataFromRowByRole(int row ,int role); QVariant CustomDataModel::getDataFromRowByRole(int row, int role) { QVariant data; if(row < vDatas.size()) { Music_Data row_data = vDatas.at(row); switch(role) { case Data_Role_NewFlag:{ data= QVariant::fromValue(row_data.NewFlag);}break; case Data_Role_TrendUp:{ data= QVariant::fromValue(row_data.TrendUp);}break; case Data_Role_TrendNum:{ data= QVariant::fromValue(row_data.TrendNum);}break; case Data_Role_ImageSouce:{ data= QVariant::fromValue(row_data.ImageSouce);}break; case Data_Role_Title:{ data= QVariant::fromValue(row_data.Title);}break; case Data_Role_Time:{ data= QVariant::fromValue(row_data.Time);}break; case Data_Role_Singer:{ data= QVariant::fromValue(row_data.Singer);}break; } } return data; }
二、Model 注册到QML
C++ 类在QML 中调用,需要将C++ 类注册到QML,注册方式有两种,一种是注册类类型,一种是注册类实例,本文注册C++ 类如下:
qmlRegisterType<CustomDataModel>("CustomDataModel",1, 0, "CustomDataModel");
QML 使用如下:
import CustomDataModel 1.0 CustomDataModel { id:tablemodel; }
三、Model 的数据和TableView 列一一对应
TableView根据Model 数据显示,不对数据做任何处理。TableView 定义如下:
TableView { anchors.fill: parent TableViewColumn {title: "NewFlag"; role: "NewFlag"; width: 70 } TableViewColumn {title: "Title"; role: "Title"; width: 70 } TableViewColumn {title: "Time"; role: "Time"; width: 70 } TableViewColumn {title: "ImageSouce"; role: "ImageSouce"; width: 70 } TableViewColumn {title: "TrendNum"; role: "TrendNum"; width: 70 } TableViewColumn {title: "TrendUp"; role: "TrendUp"; width: 70 } TableViewColumn {title: "Singer"; role: "Singer"; width: 70 } model: tablemodel }
代码运行效果如下:
四、Model 的列数据Role和TableView 列Role有差别
在QML 中调用getDataFromRowByRole 获取当前表格更新行数据,并设置相应变量
1 TableView 定义
CustomDataModel { id:tablemodel; } TableView { id:tableview anchors.fill: parent TableViewColumn{role: "NewFlag"; title: ""; width: 80; elideMode: Text.ElideRight;} TableViewColumn{role: "Title"; title: qsTr("标题"); width: 320; elideMode: Text.ElideRight;} TableViewColumn{role: "Time"; title: qsTr("时长"); width: 90;} TableViewColumn{role: "Singer"; title: qsTr("歌手"); width: 120;} headerDelegate:header_delegate itemDelegate: item_delegate rowDelegate: Rectangle { height: styleData.row < 3 ?image_row_height:row_height; //border.color:"gray"; //color: styleData.alternate?"lightgray":"white" } model:tablemodel }
2 排行delegate 数据
变量赋值方式:
property var new_flag : { var data = tablemodel.getDataFromRowByRole(styleData.row,CustomDataModel.Data_Role_NewFlag) return data }
3 标题delegate数据
4 时长delegate数据
5 歌手delegate数据
6 运行效果
总结
1 json 数据解析
void CustomDataModel::parseJsonData() { const QString filepath = ":/data/music_data.json"; QFile file(filepath); if(!file.exists()) { return ; } if(!file.open(QFile::ReadOnly)) { return; } QByteArray jsonstr = file.readAll(); QJsonParseError parseerror; QJsonDocument doc = QJsonDocument::fromJson(jsonstr,&parseerror); if(parseerror.error != QJsonParseError::NoError) { qDebug() <<"parseerror"; return; } QJsonObject obj = doc.object(); QJsonArray data = obj["Data"].toArray(); foreach(auto item , data) { Music_Data data; data.Time =item["Time"].toInt() ; data.NewFlag= item["NewFlag"].toBool(); data.TrendUp=item["TrendUp"].toBool(); data.TrendNum=item["TrendNum"].toInt(); data.ImageSouce=item["ImageSouce"].toString(); data.Singer=item["Singer"].toString(); data.Title=item["Title"].toString(); vDatas.push_back(data); } }
2 自定义model 踩坑
实现自定义model的时候不要实现,实现后造成data函数
不调用,最开始基类 选择的QAbstractItemModel 这两个函数是必须要实现,这里先贴出当时实现后不调用data函数时的代码,待后面分析原因,
virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const ; QModelIndex CustomDataModel::index(int row, int column, const QModelIndex &parent) const { return QModelIndex(); }
virtual QModelIndex parent(const QModelIndex &child) const ; QModelIndex CustomDataModel::parent(const QModelIndex &child) const { Q_UNUSED(child); return QModelIndex(); }
这篇关于QML < 6 > C++ 向QML 传递复杂数据结构 TableView 使用C++ Model QAbstractTableModel的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23增量更新怎么做?-icode9专业技术文章分享
- 2024-11-23压缩包加密方案有哪些?-icode9专业技术文章分享
- 2024-11-23用shell怎么写一个开机时自动同步远程仓库的代码?-icode9专业技术文章分享
- 2024-11-23webman可以同步自己的仓库吗?-icode9专业技术文章分享
- 2024-11-23在 Webman 中怎么判断是否有某命令进程正在运行?-icode9专业技术文章分享
- 2024-11-23如何重置new Swiper?-icode9专业技术文章分享
- 2024-11-23oss直传有什么好处?-icode9专业技术文章分享
- 2024-11-23如何将oss直传封装成一个组件在其他页面调用时都可以使用?-icode9专业技术文章分享
- 2024-11-23怎么使用laravel 11在代码里获取路由列表?-icode9专业技术文章分享
- 2024-11-22怎么实现ansible playbook 备份代码中命名包含时间戳功能?-icode9专业技术文章分享