QTreeView 复选框

QTreeView 最常见最常用的控件,很神奇的事关于它的基础用法很少。一个无限递归都没找到,就几行代码, 而大多是傻瓜的3层树形,4层树形。
使用 Qt 仿 ant 的界面 : https://ant.design/components/tree-cn/
思路: 当勾选/取消勾选一个 item 时,如果有子项都要跟着改变, 如果有父项也要做出改变(子全选则父勾选,子全不选父取消勾选,夹在中间的就是Qt::PartiallyChecked) ; 仔细看我下面的烂代码
在这里插入图片描述

#include "AllTreeView.h"
#include <QDebug>

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; j<cRowCount; ++j){
            auto cItem = new QStandardItem(QString("[%1:%2]").arg(i).arg(j));
            cItem->setCheckable(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; i<rowCount; ++i){
        QStandardItem *childItem = parentItem->child(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; i<rowCount; ++i){
        QStandardItem *childItem = item->child(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; i<rowCount; ++i){
        QStandardItem *childItem = item->child(i);
        setChildItemsEnabled(childItem,enabled);
    }
    return true;
}

  • 4
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值