说明
-
环境
Qt软件版本 : 5.9.9
实例参考书籍 : Qt5开发及实例 陆文周
系统 : Win10 专业版 -
QTreeWidget 树形控件实例
选中树形控件的父节点 或者 取消树形控件的父节点 子节点跟随父节点状态;
子节点单独选中, 父节点在半选中状态;
代码
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QTreeWidgetItem>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
void init();
void updateParentItem(QTreeWidgetItem* item);
public slots:
void treeItemChanged(QTreeWidgetItem* item, int column);
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
widget.c
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
init();
/* itemChanged() 当指定项中列的内容发生更改时,会发出此信号 */
connect(ui->treeWidget, SIGNAL(itemChanged(QTreeWidgetItem* , int)), this , SLOT(treeItemChanged(QTreeWidgetItem* , int)) );
}
Widget::~Widget()
{
delete ui;
}
void Widget::init()
{
ui->treeWidget->clear(); //* clear() 清除树内部的所有项选择
ui->treeWidget->setHeaderHidden(true); //* 设置隐藏treeWidget表头显示
//第一个分组
QTreeWidgetItem *group1 = new QTreeWidgetItem(ui->treeWidget);
group1->setText(0,"group1");
group1->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
group1->setCheckState(0,Qt::Unchecked);
QTreeWidgetItem *subItem11 = new QTreeWidgetItem(group1);
subItem11->setText(0,"subItem11");
subItem11->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
subItem11->setCheckState(0,Qt::Unchecked);
QTreeWidgetItem *subItem12 = new QTreeWidgetItem(group1);
subItem12->setText(0,"subItem12");
subItem12->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
subItem12->setCheckState(0,Qt::Unchecked);
QTreeWidgetItem *subItem13 = new QTreeWidgetItem(group1);
subItem13->setText(0,"subItem13");
subItem13->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
subItem13->setCheckState(0,Qt::Unchecked);
QTreeWidgetItem *subItem14 = new QTreeWidgetItem(group1);
subItem14->setText(0,"subItem14");
subItem14->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
subItem14->setCheckState(0,Qt::Unchecked);
//第二个分组
QTreeWidgetItem *group2 = new QTreeWidgetItem(ui->treeWidget);
group2->setText(0,"group2");
group2->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
group2->setCheckState(0,Qt::Unchecked);
QTreeWidgetItem *subItem21 = new QTreeWidgetItem(group2);
subItem21->setText(0,"subItem21");
subItem21->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
subItem21->setCheckState(0,Qt::Unchecked);
QTreeWidgetItem *subItem22 = new QTreeWidgetItem(group2);
subItem22->setText(0,"subItem22");
subItem22->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
subItem22->setCheckState(0,Qt::Unchecked);
QTreeWidgetItem *subItem23 = new QTreeWidgetItem(group2);
subItem23->setText(0,"subItem23");
subItem23->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
subItem23->setCheckState(0,Qt::Unchecked);
}
void Widget::updateParentItem(QTreeWidgetItem* item) //* 判断并设置父节点的状态
{
QTreeWidgetItem *parent = item ->parent(); //* parent() 返回项目的父级
if(parent == NULL)
{
return;
}
/* 统计选中的子节点的个数 */
int selectedCount = 0;
int childCount = parent->childCount(); //* childCount() 返回子项目的数量
for (int i = 0; i < childCount; i++)
{
QTreeWidgetItem *childItem = parent->child(i);
if(childItem->checkState(0) == Qt::Checked)
{
selectedCount++;
}
}
/* 根据选中的子节点的个数 更新父节点的状态 */
if(selectedCount <= 0)
{
parent->setCheckState(0, Qt::Unchecked);
}
else if(selectedCount > 0 && selectedCount < childCount)
{
//部分选中状态
parent->setCheckState(0, Qt::PartiallyChecked);
}
else if(selectedCount == childCount)
{
//未选中状态
parent->setCheckState(0, Qt::Checked);
}
}
void Widget::treeItemChanged(QTreeWidgetItem* item, int column)
{
QString itemText = item ->text(0);
//选中时
if(Qt::Checked == item ->checkState(0))
{
QTreeWidgetItem* parent = item ->parent();
int count = item ->childCount(); // 获取子部件数目
if(count > 0) //判断是否有子节点
{
for (int i = 0; i < count; i++)
{
//子节点也选中 有的话将下面子节点全部选中
item ->child(i) ->setCheckState(0, Qt::Checked);
}
}
else
{
//是子节点
updateParentItem(item);
}
}
else if(Qt::Unchecked == item->checkState(0))
{
int count = item ->childCount();
if(count > 0)
{
for (int i = 0; i < count; i++)
{
item ->child(i) ->setCheckState(0, Qt::Unchecked);
}
}
else
{
updateParentItem(item);
}
}
}
源码下载
https://download.csdn.net/download/occasionally/87389132
遇到的问题
在使用Qt treeWidget 控件时发现总会出现表头显示1(如图片), 在ui中删除无效, 发现可以通过下列方式解决。
解决方式1
设计界面 选中UI组件treeWidget直接设置 HeaderHidden属性
解决方式2
- 程序中使用 setHeaderHidden() 设置; 在界面构造函数中添加下面语句;
ui->treeWidget->setHeaderHidden(true);