需求
在一个QTreeWidget中,一个节点A ,下面有多个子节点 B C D等等,在勾选A的时候,下面的子节点也被勾选,同时BCD都被勾选的时候 A也自动被勾选
头文件
#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
源文件
#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);
}