【QT】重写QAbstractLIstModel,使用ListView来显示多列数据

qt提供了几个视图来进行信息的列表显示,QListView可以用来显示继承QStractListModel的字符串列表中的字符串,默认的模型里面只包含一列的内容:
这里以qml为例子,先新建一个qml的项目,示例代码如下:
先创建一个列表的只读模型,以QAbstractListModel为基类,最基础的只用实现两个函数即可:rowCount()和
data(),一个用来返回模型的行数,一个用来返回指定的模型索引的数据项:

	//返回模型的行数
    int rowCount(const QModelIndex &parent = QModelIndex()) const;
    //返回指定模型索引的数据项
    QVariant data(const QModelIndex &index, int role) const;

使用一个QStringList列表来作为内部的数据源:

    QStringList m_strValue;

现在来开始实现这两个函数:这两个函数的实现是比较简单的

int MyListModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return m_strValue.count();
}

QVariant MyListModel::data(const QModelIndex &index, int role) const
{
    if(!index.isValid())
        return QVariant();

    if(role == Qt::DisplayRole)
        return m_strValue.at(index.row());
    return QVariant();
}

再建立一个设置改列表值的函数,因为后面要将测试的model注册到qml中去,所以不方便再构造函数中将QStringList的值设置下去,所以这里添加一个setDataModel()函数,函数的定义如下:

void MyListModel::setDataModel(const QStringList &var)
{
    if(var.isEmpty())
        return ;
    m_strValue = var;
}

到这里对MyListModel的类的完善已经差不多了,接下来新增一个测试的类来添加数据到列表中去:
这里直接给出,两个文件如下:
testlistmodel.h

#ifndef TESTLISTMODEL_H
#define TESTLISTMODEL_H

#include <QObject>
#include "mylistmodel.h"

class TestListModel : public QObject
{
    Q_OBJECT
public:
    explicit TestListModel(QObject *parent = nullptr);

    MyListModel m_model;

signals:

};

#endif // TESTLISTMODEL_H

testlistmodel.cpp

#include "testlistmodel.h"

TestListModel::TestListModel(QObject *parent) : QObject(parent)
{
    QStringList list;

    for(int i = 0; i < 30; i++)
    {
        list << QString("第%1个").arg(i);
    }

    m_model.setDataModel(list);
}

最后再main.cpp中将model注册到qml中:

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "testlistmodel.h"

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;
    TestListModel model;

    engine.rootContext()->setContextProperty("testModel", &model.m_model);

    const QUrl url(QStringLiteral("qrc:/main.qml"));
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url](QObject *obj, const QUrl &objUrl) {
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    }, Qt::QueuedConnection);
    engine.load(url);

    return app.exec();
}

接下来在qml中使用ListView组件,并指定使用的model就可以了。
main.qml如下:

import QtQuick 2.12
import QtQuick.Window 2.12

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")


    ListView {
        anchors.fill: parent;
        model:testModel;
        delegate: Text {
            id: tt
            height:30;
            text: display;//Qt::DisplayRole提供一个角色名display
        }
    }
}

运行结果如下:
在这里插入图片描述
这就是一个列表显示,根据在c++中提供的数据注册到qml中来显示的,动图这里就不展示了。
可以看到这里显示的是一列的内容,如果要使用ListView来显示多列的内容,应该如何去设计model呢?这里就需要去修改数据类型,也就是不能继续用QStringList作为存储数据的了,需要重新设计一个数据类型可以去报存多个数据:这里选取的数据类型如下:

QMap<int, QMap<int,QVariant>> tmp; //使用QMap来存存放数据,内嵌一个QMap来存放每一行的各个列的数据
//内嵌的QMap也可单独设计一个类来实现,只不过在后续的其他方面也需要做不同的修改,这里先不说

定义一个这样的容器来做数据的存放,还要在原有的基础上添加几个函数,也要重写roleNames()函数,如下:
再新增一个变量,用来存放角色role:

QHash<int, QByteArray> m_roleName();

后面直接放上修改后的文件,改的内容比较多,直接在代码中标注出来:
mylistmodel.h

#ifndef MYLISTMODEL_H
#define MYLISTMODEL_H

#include <QObject>
#include <QAbstractListModel>

class MyListModel : public QAbstractListModel
{
    Q_OBJECT
public:
    MyListModel(QObject *parent = 0);
    //返回模型的行数
    int rowCount(const QModelIndex &parent = QModelIndex()) const;
    //返回指定模型索引的数据项
    QVariant data(const QModelIndex &index, int role) const;
    //设置模型数据
    void setDataModel(const QMap<int, QMap<int, QVariant>> &var);
    //返回列
    int columnCount(const QModelIndex &parent = QModelIndex()) const;
    QHash<int, QByteArray> roleNames() const;
    void insertRoleName(const int role, const QByteArray name);

private:
    QStringList m_strValue;
    QMap<int, QMap<int, QVariant>> m_map;
    QHash<int, QByteArray> m_roleName;



};

#endif // MYLISTMODEL_H

mylistmodel.cpp

#include "mylistmodel.h"

MyListModel::MyListModel(QObject* parent) : QAbstractListModel(parent)
{

}

int MyListModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return m_map.count();//改为m_map
}

QVariant MyListModel::data(const QModelIndex &index, int role) const
{
    if(!index.isValid())
        return QVariant();

    if(index.row() >= m_map.size())
        return QVariant();

    if(role >= Qt::UserRole) //使用QT提供的自定义的角色的值,累加
    {
        QMap<int, QVariant> var = m_map.value(index.row());
        return var.value(role);
    }
    return QVariant();
}

void MyListModel::setDataModel(const QMap<int, QMap<int, QVariant>> &var)
{
    if(var.isEmpty())
        return ;
    m_map = var;
}

int MyListModel::columnCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return m_roleName.count();
}

QHash<int, QByteArray> MyListModel::roleNames() const
{
    return m_roleName;
}

void MyListModel::insertRoleName(const int role, const QByteArray name)
{
    m_roleName.insert(role, name);
}

testlistmodel.cpp

#include "testlistmodel.h"

TestListModel::TestListModel(QObject *parent) : QObject(parent)
{
    QMap<int, QMap<int, QVariant>> var;

    for(int i = 0; i < 30; i++)
    {
        QMap<int,QVariant> map;

        map.insert(Qt::UserRole,QString("第%1个").arg(i));
        map.insert(Qt::UserRole+1,QString("产品%1个").arg(i));

        var.insert(i,map);

    }

    m_model.setDataModel(var);

    //添加角色
    m_model.insertRoleName(Qt::UserRole,"Column_One");
    m_model.insertRoleName(Qt::UserRole+1,"Column_Two");

}

main.qml

import QtQuick 2.12
import QtQuick.Window 2.12

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")


    ListView {
        anchors.fill: parent;
        model:testModel;
        delegate: Item {
            id: it;
            height:30;
            width:parent.width;
            Row {
                anchors.fill: parent;
                Text{
                    width:parent.width/2;
                    text: Column_One;
                }
                Text {
                    width:parent.width/2;
                    text: Column_Two;
                }
            }
        }
    }

}

以上就是所作的修改,效果图如下:
在这里插入图片描述
以上可能还有许多需要完善和修改的地方,后续会跟进修改和优化。需要源码的可以留言邮箱。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/92501.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【提升接口响应能力的最佳实践】常规操作篇

文章目录 1. 并行处理简要说明CompletableFuture是银弹吗&#xff1f;测试案例测试结论半异步&#xff0c;半同步总结 2. 最小化事务范围简要说明编程式事务模板 3. 缓存简要说明 4. 合理使用线程池简要说明使用场景线程池的创建参数的配置建议 线程池的监控线程池的资源隔离 5…

idea的debug断点的使用

添加断点&#xff08;目前不知道如何添加断点&#xff0c;就给AutoConfigurationImportSelector的每个方法都加上断点&#xff09;&#xff1a; 然后将StockApplication启动类以debug方式运行&#xff0c;然后程序就会停在119行 点击上边的step over让程序往下运行一行&#x…

HLS实现CORDIC算法计算正余弦并上板验证

硬件&#xff1a;ZYNQ7010 软件&#xff1a;MATLAB 2019b、Vivado 2017.4、HLS 2017.4、System Generator 2017.4 1、CORDIC算法计算正余弦 CORDIC算法详细分析网上有很多资料&#xff0c;它的原理是用一系列旋转去逼近目标角度&#xff0c;这一系列旋转的角度为 θ a r c t…

Git gui教程---第七篇 Git gui的使用 返回上一次提交

1&#xff0e; 查看历史&#xff0c;打开gitk程序 2&#xff0e; 选中需要返回的版本&#xff0c;右键&#xff0c;然后点击Rest master branch to here 3.出现弹窗 每个选项我们都试一下&#xff0c;从Hard开始 返回的选项 HardMixedSoft Hard 会丢失所有的修改【此处的…

【Jellyfin影音服务器】 本地部署公网远程影音库

文章目录 1. 前言2. Jellyfin服务网站搭建2.1. Jellyfin下载和安装2.2. Jellyfin网页测试 3.本地网页发布3.1 cpolar的安装和注册3.2 Cpolar云端设置3.3 Cpolar本地设置 4.公网访问测试5. 结语 1. 前言 随着移动智能设备的普及&#xff0c;各种各样的使用需求也被开发出来&…

dig批量域名逆向查询ip

dig批量域名逆向查询ip dig nocmd noall answer -f iplist.txtiplist.txt中内容 效果图&#xff1a; dig其他选项参数&#xff1a; dig www.baidu.com A # 查询A记录&#xff0c;如果域名后面不加任何参数&#xff0c;默认查询A记录 dig www.baidu.com MX # 查询MX记…

重新认识Android中的线程

线程的几种创建方式 new Thread&#xff1a;可复写Thread#run方法。也可以传递Runnable对象&#xff0c;更加灵活。缺点&#xff1a;缺乏统一管理&#xff0c;可能无限制新建线程&#xff0c;相互之间竞争&#xff0c;及可能占用过多系统的资源导致死机或oom。 new Thread(new…

LeetCode-406-根据身高重建队列

题目描述&#xff1a; 假设有打乱顺序的一群人站成一个队列&#xff0c;数组 people 表示队列中一些人的属性&#xff08;不一定按顺序&#xff09;。每个 people[i] [hi, ki] 表示第 i 个人的身高为 hi &#xff0c;前面 正好 有 ki 个身高大于或等于 hi 的人。 请你重新构造…

VB.NET调用VB6 Activex EXE实现PowerBasic和FreeBasic的标准DLL调用

VB6写的ActiveX EXE公共对象是外置进程&#xff0c;因此&#xff0c;尽管它是x86 32位的进程&#xff0c;但可以集成到 VB.NET的x64和x32程序中使用。 VS2022的VB.NET程序&#xff0c;调用ActiveX DLL对象我在上篇笔记中写了 VB.NET通过VB6 ActiveX DLL调用PowerBasic及FreeB…

Git向远程仓库与推送以及拉取远程仓库

理解分布式版本控制系统 1.中央服务器 我们⽬前所说的所有内容&#xff08;⼯作区&#xff0c;暂存区&#xff0c;版本库等等&#xff09;&#xff0c;都是在本地也就是在你的笔记本或者计算机上。⽽我们的 Git 其实是分布式版本控制系统&#xff01;什么意思呢? 那我们多人…

计算机网络(10) --- 高级IO

计算机网络&#xff08;9&#xff09; --- 数据链路层与MAC帧_哈里沃克的博客-CSDN博客数据链路层与MAC帧https://blog.csdn.net/m0_63488627/article/details/132178583?spm1001.2014.3001.5501 目录 1.IO介绍 1.IO本质 2.IO模型 2.非阻塞 3.IO多路转接 1.select 编写…

电阻器件的分类

电阻器的种类碳膜电阻膜式电阻器中的一种。气态碳氢化合物在高温和真空中分解&#xff0c;碳沉积在瓷棒或者瓷管上&#xff0c;形成一层结晶碳膜。改变碳膜厚度和用刻槽的方式变更碳膜的长度可以得到不同的阻值。碳膜电阻成本较低&#xff0c;电性能和稳定性较差&#xff0c;一…

Python自动化小技巧21——实现PDF转word功能(程序制作)

案例背景 为什么这个年代PDF转word&#xff0c;某wps居然还要收费.....很多软件都可以实现这个功能&#xff0c;但是效果都有好有坏&#xff0c;而且有的还付费&#xff0c;很麻烦。 那就用python实现这个功能吧&#xff0c;然后把代码打包为.exe的程序&#xff0c;这样随便在…

企业网络日志安全与 EventLog Analyzer

企业的网络日志安全是一项至关重要的任务。随着信息技术的迅猛发展&#xff0c;网络攻击和数据泄露的威胁也与日俱增。为了应对这些威胁&#xff0c;企业需要强大的工具来监控、分析和保护其网络日志。而ManageEngine的EventLog Analyzer正是这样一款卓越的解决方案。 网络日志…

Sentinel 控制台(集群流控管理)

规则配置 要通过 Sentinel 控制台配置集群流控规则&#xff0c;需要对控制台进行改造。我们提供了相应的接口进行适配。 从 Sentinel 1.4.0 开始&#xff0c;我们抽取出了接口用于向远程配置中心推送规则以及拉取规则&#xff1a; DynamicRuleProvider<T>: 拉取规则Dy…

网站和API支持HTTPS,最好在Nginx上配置

随着我们网站用户的增多&#xff0c;我们会逐渐意识到HTTPS加密的重要性。在不修改现有代码的情况下&#xff0c;要从HTTP升级到HTTPS&#xff0c;让Nginx支持HTTPS是个很好的选择。今天我们来讲下如何从Nginx入手&#xff0c;从HTTP升级到HTTPS&#xff0c;同时支持静态网站和…

Spark Standalone环境搭建及测试

&#x1f947;&#x1f947;【大数据学习记录篇】-持续更新中~&#x1f947;&#x1f947; 篇一&#xff1a;Linux系统下配置java环境 篇二&#xff1a;hadoop伪分布式搭建&#xff08;超详细&#xff09; 篇三&#xff1a;hadoop完全分布式集群搭建&#xff08;超详细&#xf…

神经网络学习小记录75——Keras设置随机种子Seed来保证训练结果唯一

神经网络学习小记录75——Keras设置随机种子Seed来保证训练结果唯一 学习前言为什么每次训练结果不同什么是随机种子训练中设置随机种子 学习前言 好多同学每次训练结果不同&#xff0c;最大的指标可能会差到3-4%这样&#xff0c;这是因为随机种子没有设定导致的&#xff0c;我…

Unity3D软件安装包分享(附安装教程)

目录 一、软件简介 二、软件下载 一、软件简介 Unity3D是一款全球知名的游戏开发引擎&#xff0c;由Unity Technologies公司开发。它提供了一个跨平台、多功能的开发环境&#xff0c;支持创建2D和3D游戏、交互式应用、虚拟现实、增强现实等多种类型的应用程序。以下是Unity3D…

CFC编程入门_【10分钟学会】

什么是CFC&#xff1a; 【差不多10分钟全学会】 CFC是图形化编程&#xff0c; 跟单片机的连线一样&#xff0c; 唯一的区别&#xff1a;功能块右侧是【只能输出】引脚。 只有左侧引脚可以输入输出。 有哪些控件&#xff1a; 指针&#xff1a;用于拖动功能块。 控制点&#xf…