1.前言

本博文所说的技术点适用于同时满足下面条件的所有QAbstractItemView视图类的子类:

  • 模型类从 QAbstractItemModel派生。

  • 代理类从QStyledItemDelegate派生。

因为QColumnView、QHeaderView、QListView、QTableView、QTreeView、QListWidget 、QUndoView、QTableWidget、QTreeWidget都是从QAbstractItemView继承,故本博文所说的技术点也适用于这些类。

2.需求提出

基于Qt的model/view framework技术,利用QTreeView树视图实现业务,为QTreeView设置数据模型如下:

m_pLayerTreeView->setModel(m_pLayTreeModel);

其中为m_pLayerTreeView为QTreeView类对象;m_pLayTreeModel为CLayTreeModel类对象。CLayTreeModel类实现如下:

CLayTreeModel::CLayTreeModel(const CVectorLayerMap& mpLayer, QObject *parent): QAbstractItemModel(parent)
{}QVariant CLayTreeModel::data(const QModelIndex& index, int role /*= Qt::DisplayRole*/) const
{......... // 其它代码略if (Qt::CheckStateRole == role) // 获取Qt::CheckStateRole角色{return pLayer->showOnBaseMap();}
}.........// 其它代码略

在上面代码中,通过获取Qt::CheckStateRole角色,树视图项中就会复选框出现,如下:

如果pLayer->showOnBaseMap()为true,则复选框呈勾选状态;反之则为取消勾选状态。

现在的问题是:如何实现鼠标单击勾选或取消勾选树视图中的复选框功能呢?

3.解决方法

构建一个从QStyledItemDelegate派生的代理类,将树视图对象的代理设置为该代理类对象:如下:

auto pLayerItemDelegate = new CLayerItemDelegate(this);
m_pLayerTreeView->setItemDelegate(pLayerItemDelegate);

CLayerItemDelegate类如下:

#include "layerItemDelegate.h"
#include<QDebug>
#include<QApplication>
#include<QMouseEvent>
CLayerItemDelegate::CLayerItemDelegate(QObject *parent): QStyledItemDelegate(parent)
{
}CLayerItemDelegate::~CLayerItemDelegate()
{
}bool CLayerItemDelegate::editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index)
{if (QEvent::MouseButtonPress != event->type()) // 不是鼠标单击事件,就返回{return QStyledItemDelegate::editorEvent(event, model, option, index);}auto pMouseEvent = dynamic_cast<QMouseEvent*>(event);if (Qt::LeftButton != pMouseEvent->button())  // 不是鼠标左键单击,就返回{return QStyledItemDelegate::editorEvent(event, model, option, index);}auto pt = pMouseEvent->pos();  // 鼠标点击树项的位置点(相对于树视图左上角顶点)auto itemRect = option.rect;   // 该树项在树视图占据的矩形位置(矩形坐标是相对树视图左上角顶点)auto nBtnMargin = qApp->style()->pixelMetric(QStyle::PM_ButtonMargin); // 复选框离该树项左侧或上侧的距离auto pDefaultIndicatorWidth = qApp->style()->pixelMetric(QStyle::PM_ButtonDefaultIndicator);// 复选框默认边框厚(宽)度auto nTwiceWidth = 2 * pDefaultIndicatorWidth; // 左右边框或上下边框,故需要乘2// 复选框宽度为:复选框指示器宽度加复选框左右边框厚(宽)度auto nIndicatorWidth = qApp->style()->pixelMetric(QStyle::PM_IndicatorWidth) + nTwiceWidth; // 复选框宽度// 复选框高度为:复选框指示器高度加复选框上下边框厚(宽)度auto nIndicatorHeight = qApp->style()->pixelMetric(QStyle::PM_IndicatorHeight) + nTwiceWidth; // 复选框高度auto nIndicatorTopX = itemRect.left() + nBtnMargin; // 复选框相对树项左上角的x坐标auto nIndicatorTopY = itemRect.top() + nBtnMargin;  // 复选框相对树项左上角的y坐标QRect indicatorRect(nIndicatorTopX, nIndicatorTopY, nIndicatorWidth, nIndicatorHeight); // 复选框在该树项占据的矩形auto bPtInRect = indicatorRect.contains(pt); // 鼠标在复选框占据的矩形内单击if (bPtInRect){layerCheckBoxClickedSignal(index);}return QStyledItemDelegate::editorEvent(event, model, option, index);
}

其中layerCheckBoxClickedSignal自定义的信号,参数为鼠标单击项的索引:

// 复选框被单击信号
void layerCheckBoxClickedSignal(const QModelIndex& index);

上面代码重载了editorEvent方法,当鼠标在树视图项上单击时,会进入到该函数,然后算出复选框在该树项的位置,看看鼠标单击位置是不是落在复选框在该树项占据的矩形内。如果是,就发送 layerCheckBoxClickedSignal信号,外层调用方捕捉该信号,在槽函数里将CLayTreeModel类data函数中影响Qt::CheckStateRole的布尔量设置为真或假,就可实现复选框的勾选或取消勾选。如下为代码:

connect(pLayerItemDelegate, &CLayerItemDelegate::layerCheckBoxClickedSignal, this, &CExquisiteGIS::layerCheckBoxClickedSlot);
void CExquisiteGIS::layerCheckBoxClickedSlot(const QModelIndex& index)
{// 获取该树项绑定的CVectorLayer类对象的指针auto pLayer = static_cast<CVectorLayer*>(index.internalPointer());if (nullptr == pLayer){return;}// 调用该类对象的方法auto bShowBaseMap = pLayer->showOnBaseMap();pLayer->setShowOnBaseMap(!bShowBaseMap);// 注意:一定要刷新,否则有时复选框勾选和取消勾选不能同步,即勾选(取消勾选)了依然没勾选(取消勾选)m_pLayerTreeView->update();
}

注意:一定要刷新,否则有时复选框勾选和取消勾选不能同步,即勾选(取消勾选)了依然没勾选(取消勾选)。当调用update()后会导致模型类CLayTreeModel的data函数被调用,从而实现界面复选框的刷新。

效果如下:

4.后记

上述功能,如果仅仅是为实现树视图,可以用QTreeWidget来实现。QTreeWidget类提供了对QCheckBox控件的函数和信号支持,不需要这么麻烦。另外也可以通过向QTreeView的树项插入QCheckBox控件来实现,具体参见《向QTableView、QTreeView单元格插入窗体小部件的功能实现》博文。需要说明的是:个人认为通过插入QCheckBox控件来实现,不够优雅;同时因为创建QCheckBox控件需要耗费内存,当树项很多时,在内存占用上没有前文不插入QCheckBox控件的方法来得优雅。

QAbstractItemView子类如:QTreeView、QTableView等子项单元格复选框勾选/取消勾选功能实现相关推荐

  1. Excel实现单元格下拉框选择,加VBA脚本可实现选择多个选项,默认顿号分隔,可自定义符号分隔

    1 实现单元格下拉框 来源需要用英文逗号分隔,这里输入限制为最大255字符,如果需要更多可选择单元格范围: 到这里就实现了下拉选择: 2 导入VBA脚本实现多选 按Alt+F11唤出VBA代码编辑器, ...

  2. element 表格 评分表(合并单元格,单选框按钮选分,计算表格总分)

    文件下载 >>https://download.csdn.net/download/jemycc/12837044 突然发现 vxe 会更方便 vxe官网: https://xuliang ...

  3. Jquery实现鼠标双击Table单元格变成文本框

    在jsp的body标签中代码:<td width='4%' οndblclick='edit(this,600,9)'>80</td> 在function中的代码为: func ...

  4. Excel单元格插入图片并实现单击放大或缩小功能(含VBA代码)

    文章目录 0 引言 1 提前准备VBA代码 1.1 ThisWorkbook的代码: 1.2 模块的代码: 2 设置步骤 2.1 VBA代码设置单元格 2.2 插入图片到单元格 2.3 以启用宏的方式 ...

  5. 【表格单元格可编辑】vue-elementul简单实现table表格点击单元格可编辑,点击单元格变成弹框修改数据

    前言 这是继我另一个帖子就是单元格点击变成输入框后添加的功能 因为考虑到有些时候修改单元格的信息可能点击后要修改很多,那一个输入框不好用 所以这时候就需要一个弹框可以把所有表单都显示出来修改 所以这里 ...

  6. Excel单元格下拉框引用其它Sheet中的值的方法

    以sheet1和sheet2为例.  (1)在sheet1中选择一行或一列的多个单元格  (2)在"插入"->"名称"->"定义" ...

  7. excel为单元格区域套用表格样式以及取消表格样式

    直接套用表格样式是最简单快捷的表格美化手段,而且制作出来的表格外观看起来也很专业. (常见问题) Excel表格样式的套用与创建 如何把内容粘贴到excel单元格时自动套用excel的单元格格式 ex ...

  8. QTableView中点击单元格弹出QComboBox

    主要是用QItemDelegate,写一个类继承QItemDelegate,实现createEditor(),setEditorData()和setModelData()方法 createEditor ...

  9. [Excel]单元格

    目录 文章目录 目录 一.什么是单元格? 1.全选单元格 2.选择一列 / 行单元格 3.调整单元格大小 二.设置单元格格式 1.字体/边框 2.单元格数字格式 3.换行和居中对齐 4.保护我的工作表 ...

最新文章

  1. 我画了35张图就是为了让你深入 AQS
  2. Property with #39;retain (or strong)#39; attribute must be of object type
  3. 用python学编程_用Python学编程
  4. 90. Leetcode 剑指 Offer 62. 圆圈中最后剩下的数字 (动态规划-基础题)
  5. Scala中Unit 类型、Null 类型和 Nothing 类型
  6. Hadoop使用MultipleOutputs输出多文件或者指定命名
  7. ×××站点的路由(隧道、接口)模式和策略模式
  8. plt.subplots中的ax = ax.flatten()
  9. cron 12点执行_【技术指南】Crontab调度重复执行的任务
  10. 【刷题】BZOJ 4503 两个串
  11. turbo c 2.0 官方下载_iMyFone MintPDF英文版官方下载2.0.10
  12. eclipse安装SVN插件
  13. 数学史思维导图_如何学好高中数学,看懂思维导图,秒懂系列之集合
  14. GMS地下水数值模拟
  15. JAVA数据库访问控制框架设计与使用
  16. python安装库之----有些库库真是小妖精
  17. 计算机上怎么计算x的n次方,计算x的n次方(用函数)
  18. 美育在计算机教育中应用,浅谈在小学信息技术课堂中有效实施美育.
  19. 个人作业--四则运算3
  20. CryptoJS的hmac-sha1算法使用(转base64)——2022.11.18

热门文章

  1. 接口文档示例(详解)
  2. SpringReport--报表设计器的使用
  3. 阿里云、华为云、谷歌云都已入局,盘点13家云计算厂商的RPA
  4. 计算机工作流程flash动画,计算机动画设计:FlashCS3
  5. android 名片识别 简书,简书,也有了我的名片
  6. 软件架构(软件体系结构)-设计原则篇(七大设计原则)
  7. 【考研数学】概率论与数理统计
  8. 使用 Echarts 插件完成中国地图
  9. 构造函数 和 析构函数 能否抛出异常
  10. python金融基础知识_Python金融时间序列分析(一):基础知识