如果想使用表格来呈现数据,Qt提供了一个方便的部件QTableWidget,但是直接用它实现一些功能可能比较困难。这里将介绍一种强大、灵活的方式来操作表格。

一、模型/视图架构

在这个架构中,模型用于存储数据,视图用于呈现数据,除此之外,还有一个称为委托的部分,委托显示视图中的每一项,并为可编辑的项提供合适的编辑器。

三者的关系如下图所示——

这篇博客只介绍模型/视图的部分,接下来用一个简单的例子来说明如何使用。

二、要实现的功能

以网易云音乐为例,它的部分搜索界面是这样的:

现在,我们依照网易云音乐做一个下面的窗口,并实现额外的一些功能。

要实现的功能:

1.网上搜索:从网上搜索歌曲的数据并呈现在左边的表格中;

2.本地搜索并选中:在左边的表格中进行搜索,选中与关键字相匹配的行;

3.本地搜索并过滤:在左边的表格中进行搜索,只显示与关键字相匹配的行,过滤隐藏不匹配的行。

三、联网搜索

1.准备工作

左边的表格使用 QTableView 。

为了存储数据,需要使用合适的模型,在这里我们使用 QStandardItemModel 。

同时为了实现过滤,需要另一个代理模型 QSortFilterProxyModel 。

  1. //数据模型
  2. class MusicInfoModel : public QStandardItemModel
  3. {
  4. public:
  5. void loadData(const QString &strKeyword);//用于加载网上搜索得到的数据
  6. }
  7. //主窗口
  8. class MainWidget : public QWidget
  9. {
  10. private slots:
  11. void searchOnlineSlot(); //网上搜索
  12. void searchAndSelcLocalSlot(); //本地搜索并选择
  13. void searchAndFilterLocalSlot(); //本地搜索并过滤
  14. private:
  15. MusicInfoModel *m_pInfoModel; //数据模型
  16. QSortFilterProxyModel *m_pFilterModel; //过滤代理模型
  17. }

  

以上只列出重要的成员变量和成员函数。

为了方便加载数据,我们将QStandardItemModel子类化,在子类中声明一个加载数据的函数 loadData 。

在主窗口的构造函数中初始化视图和模型——

  1. m_pInfoModel = new MusicInfoModel(this);
  2. m_pFilterModel = new QSortFilterProxyModel(this);
  3. m_pFilterModel->setSourceModel(m_pInfoModel);
  4. ui.musicInfoTblView->setModel(m_pFilterModel);

从上面可以看到,表格的视图模型是代理模型filterModel,而不是实际包含数据的模型infoModel。

2.加载数据

接下来网上搜索,获得数据并加载到表格中

首先定义歌曲信息的数据结构

  1. //歌曲信息的数据结构
  2. struct SongInfo
  3. {
  4. public:
  5. QString strName; //歌曲标题
  6. QString strSinger; //歌手名字
  7. QString strAlbum; //专辑名称
  8. };

完成数据模型中加载数据的函数:

  1. void MusicInfoModel::loadData(const QString &strKeyword)
  2. {
  3. QList<SongInfo> listSongInfo; //歌曲信息的list
  4.  
  5. //...省略的步骤
  6. //根据关键字strKeyword从网上搜索
  7. //并将搜索结果存储到listSongInfo中
  8.  
  9. //清除数据模型中之前存在的数据,并重新设置表头(因为clear会把表头也清除掉)
  10. clear();
  11. setHorizontalHeaderLabels(QStringList() << QString::fromLocal8Bit("音乐标题") << QString::fromLocal8Bit("歌手") << QString::fromLocal8Bit("专辑"));
  12. //遍历list,将数据存在表中
  13. for (SongInfo songItem : listSongInfo)
  14. {
  15. QList<QStandardItem *> listItems;
  16. QStandardItem *pTitle = new QStandardItem(songItem.strName);
  17. QStandardItem *pSinger = new QStandardItem(songItem.strSinger);
  18. QStandardItem *pAlbum = new QStandardItem(songItem.strAlbum);
  19. listItems << pTitle << pSinger << pAlbum;
  20. appendRow(listItems);//加载一行数据
  21. }
  22. }

注意:表中的每一项是一个QStandardItem,在加载一行之前,需要先把他们存储在一个QList中,然后调用appendRow函数,一次完成加载3列。

接下来,我们在主界面中调用数据模型对象的loadData函数,即可将数据全部填到表格中。

四、本地搜索并过滤

过滤很简单,只需要使用QSortFilterProxyModel中的相关函数。

  1. void MainWidget::searchAndFilterLocalSlot()
  2. {
  3. QString strKeyword = ui.textEdit->text();
  4. m_pFilterModel->setFilterFixedString(strKeyword);//根据字符串过滤
  5. }

一些有用的函数:

void setFilterKeyColumn(int column) :设置根据表的哪一列进行过滤,默认值为0,如果设置成-1,则会根据所有列进行搜索。

setFilterFixedString(const QString &) :根据固定的字符串进行过滤。

setFilterRegExp(const QRegExp &) :根据正则表达式进行过滤。

五、本地搜索并选中

  1. void MainWidget::searchAndSelcLocalSlot()
  2. {
  3. QItemSelection selection;
  4. int iFirstSelcRow = -1;
  5. for (int i = 0; i < m_pFilterModel->rowCount(); ++i)
  6. {
  7. //获得每一行的歌名、歌手名、专辑名
  8. QModelIndex songIndex = m_pFilterModel->index(i, 0);
  9. QModelIndex singerIndex = m_pFilterModel->index(i, 1);
  10. QModelIndex albumnIndex = m_pFilterModel->index(i, 2);
  11. QString strSong = m_pFilterModel->data(songIndex).toString();
  12. QString strSinger = m_pFilterModel->data(singerIndex).toString();
  13. QString strAlbumn = m_pFilterModel->data(albumnIndex).toString();
  14. //判断是否符合条件
  15. if (strSong.contains(strKeyword) || strSinger.contains(strKeyword) || strAlbumn.contains(strKeyword))
  16. {
  17. if (iFirstSelcRow == -1)
  18. {
  19. iFirstSelcRow = i;
  20. }
  21. //增加选中项
  22. QItemSelection rowSelc(songIndex, songIndex);
  23. selection.merge(rowSelc, QItemSelectionModel::Select);
  24. }
  25. }
  26. //清除之前所有选中项,并选中现在的所有匹配项
  27. QItemSelectionModel *pSelcModel = ui.musicInfoTblView->selectionModel();
  28. pSelcModel->clearSelection();
  29. pSelcModel->select(selection, QItemSelectionModel::Rows | QItemSelectionModel::Select);
  30. //视图滚动到第一个选中项的位置
  31. if (iFirstSelcRow != -1)
  32. {
  33. ui.musicInfoTblView->scrollTo(m_pFilterModel->index(iFirstSelcRow, 0));
  34. }
  35. }

最终的简陋窗口:

以上只是视图/模型的使用作简单介绍,更多用法还请在实践中自行查找官方文档。

Qt——用于表格QTableView的模型的更多相关文章

  1. Qt实现表格控件-支持多级列表头、多级行表头、单元格合并、字体设置等

    目录 一.概述 二.效果展示 三.定制表头 1.重写数据源 2.重写QHeaderView 四.设置属性 五.相关文章 原文链接:Qt实现表格控件-支持多级列表头.多级行表头.单元格合并.字体设置等 ...

  2. Qt之表格控件蚂蚁线

    一.蚂蚁线 摘自互动百科:在图像影像软件中表示选区的动态虚线,因为虚线闪烁的样子像是一群蚂蚁在跑,所以俗称蚂蚁线.在Poshop,After Effect等软件中比较常见. 背景:用过excel的同学 ...

  3. Qt实现表格树控件-自绘树节点虚线

    目录 一.开心一刻 二.自绘树节点? 三.效果展示 四.实现思路 1.可扩展接口 2.函数重写 3.同步左侧表头 五.相关文章 原文链接:Qt实现表格树控件-自绘树节点虚线 一.开心一刻 一程序员第一 ...

  4. Qt实现表格树控件-支持多级表头

    目录 一.概述 二.效果展示 三.实现方式 四.多级表头 1.数据源 2.表格 3.QStyledItemDelegate绘制代理 五.测试代码 六.相关文章 原文链接:Qt实现表格树控件-支持多级表 ...

  5. qt model/view 架构自定义模型之QFileSystemModel

    # -*- coding: utf-8 -*- # python:2.x #QFileSystemModel """ Qt  内置了两种模型:QStandardItemM ...

  6. qt model/view 架构自定义模型之QStringListModel

    # -*- coding: utf-8 -*- # python:2.x #QStringListModel #QStringListModel 是最简单的模型类,具备向视图提供字符串数据的能力. # ...

  7. Qt 学习之路:模型-视图高级技术

    PathView PathView是 QtQuick 中最强大的视图,同时也是最复杂的.PathView允许创建一种更灵活的视图.在这种视图中,数据项并不是方方正正,而是可以沿着任意路径布局.沿着同一 ...

  8. Qt将表格table保存为excel(odbc方式)

    首先是保存excel的方法,可参照: http://dzmlmszp.blog.163.com/blog/static/179271962014819111812531/ ok,进入正题. 现在我有一 ...

  9. Qt在表格中加入控件

    任务:使用QTableWidget动态生成表格,在每行的某两列中加入QComboBox下拉框控件和QPushButton按钮控件 有添加,删除,编辑功能,每行的按钮可以浏览文件夹并选择文件 1.新建一 ...

随机推荐

  1. 初学者浅度剖析eShopOnContainers 里面用到的MediatR .

    一.介绍 简单了解下开源项目 MedatR, eShopOnContainers, MediatR作者Jimmy Bogard : Simple mediator implementation in ...

  2. rest的Web服务端获取http请求头字段

    如上图所示 输出的i就是获取的头字段的值 (仅自己记录)

  3. JUC——线程同步锁(Condition精准控制)

    在进行锁处理的时候还有一个接口:Condition,这个接口可以由用户来自己进行锁的对象创建. Condition的作用是对锁进行更精确的控制. Condition的await()方法相当于Objec ...

  4. 六大iT公司的组织结构

  5. Netty源码分析第6章(解码器)---->第4节: 分隔符解码器

    Netty源码分析第六章: 解码器 第四节: 分隔符解码器 基于分隔符解码器DelimiterBasedFrameDecoder, 是按照指定分隔符进行解码的解码器, 通过分隔符, 可以将二进制流拆分 ...

  6. Netty源码分析第8章(高性能工具类FastThreadLocal和Recycler)---->第4节: recycler中获取对象

    Netty源码分析第八章: 高性能工具类FastThreadLocal和Recycler 第四节: recycler中获取对象 这一小节剖析如何从对象回收站中获取对象: 我们回顾上一小节demo的ma ...

  7. PPIO去中心化存储的了解和记录

    目录 介绍 FileCoin P2P技术给去中心化云存储的好处 剩余资源的再次使用 市场竞争会激发民间的智慧 PPIO的2种冗余模式 全副本模式 纠删副本模式 为什么PPIO要设计支付代理节点? 一些 ...

  8. XSS构造技巧

    利用字符编码: 百度曾经出过一个XSS漏洞,在一个<script>标签中输出一个变量,其中转义了双引号: var redirectUrl="\";alert(/XSS/ ...

  9. 局域网arpspoof欺骗获取cookie/图片/密码

    开启路由转发功能 查看IP转发功能是否打开 默认是不开起,0,我这里是修改后的,显示1. 修改转发功能,1为允许. 修改成功后再进行Arpspoof欺骗 如果开始劫持后,自己电脑无法联网了 ??? 检 ...

  10. python3使用csv包,读写csv文件

    python操作csv,现在很多都用pandas包了,不过python还是有一个原始的包可以直接操作csv,或者excel的,下面举个例子说明csv读写csv文件的方法: import os impo ...