Checked, unchecked and semi-checked of QTreeWidget

demand

In a QTreeWidget, a node A has multiple child nodes BCD and so on. When A is checked, the child nodes below are also checked. At the same time, when BCD is checked, A is also checked automatically

head File

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include<QTreeWidget>
#include<QTreeWidgetItem>
namespace Ui {
    
    
class Widget;
}

class Widget : public QWidget
{
    
    
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();
private:
   void initUi();
   void updateChildItemCheckState(QTreeWidgetItem *item);
   void updateParentItemCheckState(QTreeWidgetItem *item);
   int getChildItemCheckedCount(const QTreeWidgetItem *item);
private slots:
   void onTreeItemChanged(QTreeWidgetItem *item,int col);
private:
    Ui::Widget *ui;
};

#endif // WIDGET_H

Source File

#include "widget.h"
#include "ui_widget.h"
#include<QSignalBlocker>
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    
    
    ui->setupUi(this);
    initUi();
    connect(ui->treeWidget,&QTreeWidget::itemChanged,this,&Widget::onTreeItemChanged);
}

Widget::~Widget()
{
    
    
    delete ui;
}

void Widget::initUi()
{
    
    
   QTreeWidgetItem *itemRoot = new QTreeWidgetItem;
   itemRoot->setText(0,"Root");
   itemRoot->setCheckState(0,Qt::Unchecked);
   ui->treeWidget->addTopLevelItem(itemRoot);
   for(int i  = 0;i<3;++i)
   {
    
    
          QTreeWidgetItem *item = new QTreeWidgetItem(itemRoot);
          {
    
    
              for(int j = 0;j<3;++j)
              {
    
    
                  QTreeWidgetItem *childItem = new QTreeWidgetItem(item);
                  childItem->setText(0,tr("col---child:----%1").arg(QString::number(j)));
                  childItem->setCheckState(0,Qt::Unchecked);
              }
              item->setExpanded(true);
          }
          item->setText(0,tr("col--parent:----%1").arg(QString::number(i)));
          item->setCheckState(0,Qt::Unchecked);

   }
   itemRoot->setExpanded(true);
}

void Widget::updateChildItemCheckState(QTreeWidgetItem *item)
{
    
    
   if(item == nullptr)
   {
    
    
       return ;
   }
   int childCount  =  item->childCount();
   auto checkState = item->checkState(0);
   for(int i = 0;i<childCount;++i)
   {
    
    
        auto childItem =   item->child(i);
        if(childItem)
        {
    
    
            childItem->setCheckState(0,checkState);
            updateChildItemCheckState(childItem);
        }
   }
}

void Widget::updateParentItemCheckState(QTreeWidgetItem *item)
{
    
    
    if(item == nullptr)
    {
    
    
        return ;
    }
    auto parentItem = item->parent();
    if(parentItem == nullptr)
    {
    
    
        return ;
    }
    int childCount = parentItem->childCount();
    int childCheckedCount =  getChildItemCheckedCount(parentItem);
    if(childCount == childCheckedCount)//孩子节点全被勾选 则 自身也应该被勾选
    {
    
    
        parentItem->setCheckState(0,Qt::Checked);
    }
    else if(childCheckedCount > 0)//有子节点被勾选 则是半选中状态
    {
    
    
        parentItem->setCheckState(0,Qt::PartiallyChecked);
    }
    else if(childCheckedCount == 0)//子节点都未勾选
    {
    
    
        parentItem->setCheckState(0,Qt::Unchecked);

    }
     updateParentItemCheckState(parentItem);//更新自身的父节点
}

int Widget::getChildItemCheckedCount(const QTreeWidgetItem *item)
{
    
    
    // 获取子节点中 子节点勾选的数目
   if(item == nullptr)
   {
    
    
       return 0;
   }
   int childCount =  item->childCount();
   int checkedCount = 0;
   for(int iter = 0;iter<childCount;++iter)
   {
    
    
       auto childItem = item->child(iter);
       if(childItem)
       {
    
    
        if(childItem->checkState(0) == Qt::Checked)
        {
    
    
            ++checkedCount;
        }
       }
   }
   return checkedCount;
}

void Widget::onTreeItemChanged(QTreeWidgetItem *item, int col)
{
    
    
  if(item == nullptr)
  {
    
    
    return ;
  }
 QSignalBlocker blocker(ui->treeWidget);
  updateChildItemCheckState(item);
  updateParentItemCheckState(item);

}

Guess you like

Origin blog.csdn.net/weixin_39308337/article/details/106353102