QTreeView 复选框

最常见最常用的控件 , 很神奇的事关于它的基础用法很少 。一个无限递归都没找到 , 就几行代码 ,  而大多是傻瓜的3层树形 , 4层树形 。
使用 Qt 仿 ant 的界面 :
【QTreeView 复选框】思路: 当勾选/取消勾选一个 item 时 , 如果有子项都要跟着改变 ,  如果有父项也要做出改变(子全选则父勾选 , 子全不选父取消勾选 , 夹在中间的就是Qt::) ; 仔细看我下面的烂代码
#include "AllTreeView.h"#include AllTreeView::AllTreeView(QWidget *parent) : QTreeView(parent){//禁止编辑this->setEditTriggers(QTreeView::NoEditTriggers);//自定义右键菜单this->setContextMenuPolicy(Qt::CustomContextMenu);//最喜欢用的model, 不喜欢自己写model浪费时间_model = new QStandardItemModel(this);//隐藏头部this->setHeaderHidden(true);//水平头部描述(已经被隐藏了)QStringList headList;headList<<"item";_model->setHorizontalHeaderLabels(headList);_model->setColumnCount(headList.size());for(int i=0; i<20; ++i){auto item = new QStandardItem(QString("%1").arg(i));item->setCheckable(true);int cRowCount = 2;/*rand() %300;*/for(int j=0; jsetCheckable(true);item->appendRow(cItem);for(int n=0; n<4; ++n){auto nItem = new QStandardItem(QString("[%1:%2]:[%3]").arg(i).arg(j).arg(n));nItem->setCheckable(true);cItem->appendRow(nItem);for(int m=0; m<4; ++m){auto mItem = new QStandardItem(QString("[%1:%2]:[%3][%4]").arg(i).arg(j).arg(n).arg(m));mItem->setCheckable(true);nItem->appendRow(mItem);}}}item->setText(QString("%1 (%2)").arg(item->text()).arg(item->rowCount()));_model->appendRow(item);}connect ( _model ,SIGNAL(itemChanged(QStandardItem*)) , this ,SLOT(slotItemChanged(QStandardItem*)));this->setModel(_model);//全部展开//this->expandAll();}AllTreeView::~AllTreeView(){if(_model) delete _model;}void AllTreeView::slotItemChanged(QStandardItem *item){if (!item)return ;_model->blockSignals(true);setChildItems(item,item->checkState() == Qt::Checked ? true : false);setParentItems(item,item->checkState() == Qt::Checked ? true : false);_model->blockSignals(false);this->viewport()->update();}bool AllTreeView::setParentItems(QStandardItem * item,bool check){if(!item || !item->parent()) return false;QStandardItem *parentItem = item->parent();int rowCount = parentItem->rowCount();Qt::CheckState checkState = check ? Qt::Checked : Qt::Unchecked;int checkedCount = 0;int uncheckedCount = 0;for(int i=0; ichild(i);if(childItem->checkState() == Qt::Checked && check ){++checkedCount;}else if(childItem->checkState() == Qt::Unchecked && !check){++uncheckedCount;}else{checkState = Qt::PartiallyChecked;break;}}if(checkedCount != rowCount && uncheckedCount !=rowCount){checkState = Qt::PartiallyChecked;}parentItem->setCheckState(checkState);setParentItems(parentItem,check);return true;}bool AllTreeView::setChildItems(QStandardItem * item,bool check){if(!item) return false;item->setCheckState(check ? Qt::Checked : Qt::Unchecked);int rowCount = item->rowCount();for(int i=0; ichild(i);setChildItems(childItem,check);}return true;}//启用/禁用 item及子项bool AllTreeView::setChildItemsEnabled(QStandardItem * item,bool enabled){if(!item) return false;item->setEnabled(enabled);int rowCount = item->rowCount();for(int i=0; ichild(i);setChildItemsEnabled(childItem,enabled);}return true;}