QTreeView/QTableView中利用QStandardItem实现复选框三种形态变化
https://www.techieliang.com/2017/12/729/ 原文地址

using_checkbox_item.h
/**
* @file using_checkbox_item.h
* @brief 本文件包含支持复选框item类声明。
* @version 1.0.0.0
* @date 2017.12.18
* @author Techie亮
*/
#ifndef _H_USINGCHECKBOXITEM_
#define _H_USINGCHECKBOXITEM_
#include <QStandardItem>
#include <QString>
/**
* @brief 支持复选框item类
* 支持复选框三态转变-全选对勾、全不选空白、半选黑点
* 子类会自动通知父子节点item,若不符合设计需要可仿照此方式在model中的setDate重现
*/
class UsingCheckboxItem : public QStandardItem {
public:
/**
* @brief 构造函数
* @param item显示内容
*/
explicit UsingCheckboxItem(const QString &text);
/**
* @brief setData重写
* @param value data值
* @param role data类型
*/
virtual void setData(const QVariant &value, int role = Qt::UserRole + 1);
};
#endif // _H_USINGCHECKBOXITEM_
using_checkbox_item.cpp
#include "using_checkbox_item.h"
//构造函数
UsingCheckboxItem::UsingCheckboxItem(const QString &text)
: QStandardItem(text) {
setCheckable(true);
}
//setData重写
void UsingCheckboxItem::setData(const QVariant &value, int role) {
if(role == Qt::CheckStateRole) {//针对复选框变动做操作
Qt::CheckState check_state = (Qt::CheckState)value.toInt();
QString mtext=text();
switch (check_state) {
case Qt::Unchecked: {//取消
for(int i = 0, num = rowCount(); i < num; i++) {
child(i)->setData(Qt::Unchecked, Qt::CheckStateRole);
}
//修改内容-必须先修改自己再通知父节点
QStandardItem::setData(value,role);
//通知父节点,我取消了选择,直接告诉父节点半选即可
if(parent())parent()->setData(Qt::PartiallyChecked, role);
}
return;//此事件已完成直接return
case Qt::PartiallyChecked: {//半选
Qt::CheckState current_state = checkState();//当前状态
int checked_num = 0;//被选择的数量
int unchecked_num = 0;//未选择的数量
bool is_partially = false;
Qt::CheckState child_state;
int m_rowCount = rowCount();
//遍历所有子节点
for(int i = 0; i < m_rowCount; i++) {
child_state = child(i)->checkState();
//子节点半选,则直接半选
switch (child_state) {
case Qt::PartiallyChecked:is_partially = true;break;
case Qt::Unchecked:unchecked_num++;break;
case Qt::Checked:checked_num++;break;
default:checked_num++;break;
}
}
//根据子节点状态确定当前节点应该设置的状态
Qt::CheckState now_state;
if(is_partially)
now_state = Qt::PartiallyChecked;
else if(checked_num == m_rowCount)
now_state = Qt::Checked;
else if(unchecked_num == m_rowCount)
now_state = Qt::Unchecked;
else
now_state = Qt::PartiallyChecked;
//修改状态并通知父节点
if(current_state != now_state) {
//修改内容-必须先修改自己再通知父节点
QStandardItem::setData(now_state,role);
//通知父节点,我的状态更改,也就是父节点进入半选
if(parent())parent()->setData(Qt::PartiallyChecked, role);
}
}
return;//此事件已完成直接return
case Qt::Checked: {//全选
for(int i = 0, num = rowCount(); i < num; i++) {
child(i)->setData(Qt::Checked, Qt::CheckStateRole);
}
//修改内容-必须先修改自己再通知父节点
QStandardItem::setData(value,role);
//通知父节点,我被选了,也就是父节点进入半选
if(parent()) {
parent()->setData(Qt::PartiallyChecked, role);
}
}
return;//此事件已完成直接returndefault://如果出现此情况就是错了,可以加错误处理break;}}QStandardItem::setData(value,role);}
测试函数
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <qstandarditemmodel.h>
#include "using_checkbox_item.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow) {
ui->setupUi(this);
QStandardItemModel *m = new QStandardItemModel(this);
ui->treeView->setModel(m);
auto i1 = new UsingCheckboxItem("1");
auto i2 = new UsingCheckboxItem("2");
m->appendRow(i1);
m->appendRow(i2);
auto i11 = new UsingCheckboxItem("1-1");
auto i12 = new UsingCheckboxItem("1-2");
i1->appendRow(i11);
i1->appendRow(i12);
auto i111 = new UsingCheckboxItem("1-1-1");
auto i112 = new UsingCheckboxItem("1-1-2");
i11->appendRow(i111);
i11->appendRow(i112);
auto i121 = new UsingCheckboxItem("1-2-1");
auto i122 = new UsingCheckboxItem("1-2-2");
i12->appendRow(i121);
i12->appendRow(i122); auto i21 = new UsingCheckboxItem("2-1");
auto i22 = new UsingCheckboxItem("2-2");
i2->appendRow(i21);
i2->appendRow(i22);
auto i211 = new UsingCheckboxItem("2-1-1");
auto i212 = new UsingCheckboxItem("2-1-2");
i21->appendRow(i211);
i21->appendRow(i212);
auto i221 = new UsingCheckboxItem("2-2-1");
auto i222 = new UsingCheckboxItem("2-2-2");
i22->appendRow(i221);
i22->appendRow(i222);
}
说明
- 重写了setData方法,但仅对CheckStateRole类型data做了操作,其余类型通过最后的QStandardItem::setData(value,role)直接使用默认方式
- setData中每个case后均直接return,因为会根据value和父子类情况对实际要使用value做修改,最终赋值给QStandardItem::setData不一定是参数value,所以若不返回,必然会调用最后一样导致出错
- 系统默认只有两个状态切换选中和补选中,所以可以借用这个特性,当一个节点状态修改时都通知其父类为PartiallyChecked部分选中状态,由父节点自行判断子节点情况并设置自身状态
- 注意一定要先修改自身状态以后在通知父节点,否则在父节点函数运行过程中自身仍为未修改状态,会导致判断错误
- 在PartiallyChecked的case中判断了一下新旧状态是否改变,若改变会向上一父节点继续传递消息,不改变则立刻停止减少运算量
- 若子节点存在PartiallyChecked状态的,则当前节点一定为PartiallyChecked
- 注意最顶级item是没有parent的所以想父节点传递消息前一定要判断parent是否为nullptr
- 选择一个节点那么此节点一定会在全选-不选两个状态切换,而部分选择仅存在于此节点的子节点发生变动,所以全选-不选两个case直接对所有子节点赋值
QTreeView/QTableView中利用QStandardItem实现复选框三种形态变化的更多相关文章
- extjs 中动态给gridpanel 复选框赋值
最近在搞extjs时需要动态根据数据给gridpanel的复选框赋值 网上看了很多 ,多不行,最后找到一个好使的方法 如下: RBACformPanel.getSelectionModel().sel ...
- 关于netbeans中的JComboBox(复选框)
以最近写的选课系统中添加课程项为例 1.往复选框中放入选项(根据数据库添加) (1)首先将 属性—>model中默认Item1234清空 (2)获得数据库中的数据并放入. SelectCour ...
- 关于Unity中NGUI的Checkbox复选框、Slider滑动条和Button的6种触发回调事件的方式
Checkbox复选框 1.创建一个NGUI背景Sprite1节点 2.打开NGUI---->Open---->Prefab Toolbar---->选择一个复选框节点,拖拽到背景节 ...
- mui开发中获取单选按钮、复选框的值
js获取单选按钮的值 function getVals(){ var res = getRadioRes('rds'); if(res == null){mui.toast('请选择'); retur ...
- [原创]delphi一次性批量在TScrollBox中显示N个复选框TCheckBox的源码
unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System ...
- Extjs3.4 grid中添加一列复选框
var sm = new Ext.grid.CheckboxSelectionModel(); var cm = new Ext.grid.ColumnModel( [ sm, new Ext.gri ...
- Qt之QTableView添加复选框(QAbstractTableModel)
简述 使用QTableView,经常会遇到复选框,要实现一个好的复选框,除了常规的功能外,还应注意以下几点: 三态:不选/半选/全选 自定义风格(样式) 下面我们介绍一下常见的实现方式: 编辑委托. ...
- Qt树形控件QTreeView使用1——节点的添加删除操作 复选框的设置
QtreeView是ui中最常用的控件,Qt中QTreeWidget比QTreeView更简单,但没有QTreeView那么灵活(QTreeWidget封装的和MFC的CTreeCtrl很类似,没有m ...
- 在php中验证复选框
PHP接收多个同名复选框信息不像ASP那样自动转换成为数组,这给使用带来了一定不便.但是还是有解决办法的,就是利用javascript做一下预处理.多个同名复选框在javascript中还是以数组的形 ...
随机推荐
- 问题 C: 调酒壶里的酸奶 广搜或深搜+记忆化搜索
问题 C: 调酒壶里的酸奶 时间限制: 1 Sec 内存限制: 128 MB提交: 284 解决: 97[提交] [状态] [命题人:外部导入] 题目描述 最近小w学了一手调酒的技巧,这么帅的操作 ...
- ArduinoNano卡在上传,无法烧录
卡在“上传...”.过了很久被告知失败. 上午在开发版管理器中将Arduino AVR Boards从1.6.20升级到1.6.22,出现这个问题. 再安装回1.6.20,问题未被解决. 查阅资料无果 ...
- java.lang.Exception: The server rejected the connection: None of the protocols were accepted
solution for this is from comment for https://issues.jenkins-ci.org/browse/JENKINS-29616. The follow ...
- 深度学习(六)keras常用函数学习
原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/9769301.html Keras是什么? Keras:基于Theano和TensorFlow的 ...
- AutoMapper控件
1.下载AutoMapper控件. 2.定义类,实现Profile. 3.在定义类的构造方法中使用如下代码进行转换 // 1.匹配,o,t代表TDestination;s代表TSource,返回TDe ...
- Window10安装Django,并创建第一个Django项目
1.在cmd中输入pip install Django==1.11.7,安装的版本为:1.11.7. 2.安装完成后输入: >>> import django >>> ...
- InterView之C/CPP
CPP 引用 什么是"引用"?申明和使用"引用"要注意哪些问题? 答:引用就是某个目标变量的别名(alias),对应用的操作与对变量直接操作效果完全相同.申明一 ...
- Linux文件夹打包发送到本地
tar -cvf script.tar scriptsz script.tar 具体: sz/rz命令: 一般来说,linux服务器大多是通过ssh来进行远程的登陆和管理的,如何在命令方式下上传和 ...
- 亿级别记录的mongodb分页查询java代码实现
1.准备环境 1.1 mongodb下载 1.2 mongodb启动 C:\mongodb\bin\mongod --dbpath D:\mongodb\data 1.3 可视化mongo工具Robo ...
- 基础爬虫,谁学谁会,用requests、正则表达式爬取豆瓣Top250电影数据!
爬取豆瓣Top250电影的评分.海报.影评等数据! 本项目是爬虫中最基础的,最简单的一例: 后面会有利用爬虫框架来完成更高级.自动化的爬虫程序. 此项目过程是运用requests请求库来获取h ...