QTreeWidget这个类是一个树形控件,要和QTreeWidgetItem一起使用,因为QTreeWidget是一个整体的控件,而QTreeWidgetItem是树的节点.
首先在widget中拖拽一个QTreeWidget控件.
然后定义init()函数用于初始化控件
void Widget::init()
{
ui->treeWidget->clear();
//第一个分组
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->setFlags(Qt::ItemIsUserCheckable|Qt::ItemIsEditable|Qt::ItemIsSelectable);
subItem11->setText(0,"subItem1");
subItem11->setCheckState(0,Qt::Unchecked);
QTreeWidgetItem *subItem12=new QTreeWidgetItem(group1);
subItem12->setFlags(Qt::ItemIsUserCheckable|Qt::ItemIsEnabled|Qt::ItemIsSelectable);
subItem12->setText(0,"subItem2");
subItem12->setCheckState(0,Qt::Unchecked);
QTreeWidgetItem *subItem13=new QTreeWidgetItem(group1);
subItem13->setFlags(Qt::ItemIsUserCheckable|Qt::ItemIsEnabled|Qt::ItemIsSelectable);
subItem13->setText(0,"subItem3");
subItem13->setCheckState(0,Qt::Unchecked);
QTreeWidgetItem *subItem14=new QTreeWidgetItem(group1);
subItem14->setFlage(Qt::ItemIsUserCheckable|Qt::ItemIsEnabled|Qt::ItemIsSelectable);
subItem14->setText(0,"subItem4");
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->setFlags(Qt::ItemIsUserCheckable|Qt::ItemIsEnabled|Qt::ItemIsSelectable);
subItem21->setText(0,"subItem2");
subItem21->setCheckState(0,Qt::Unchecked);
QTreeWidgetItem *subItem22=new QTreeWidgetItem(group2);
subItem22->setFlags(Qt::ItemIsUserCheckable|Qt::ItemIsEnabled|Qt::ItemIsSelectable);
subItem22->setText(0,"subItem22");
subItem22->setCheckState(0,Qt::Unchecked);
QTreeWidgetItem *subItem23=new QTreeWidgetItem(group2);
subItem23->setFlags(Qt::ItemIsUserCheckable|Qt::ItemIsEnabled|Qt::ItemIsSelectable);
subItem23->setText(0,"subItem23");
subItem23->setCheckState(0,Qt::Unchecked);
}
树形控件的特征就是当选中顶层的树形节点时,子节点全部被选中,当取消顶层树形节点时,子节点全部被取消状态.
首先我们先来看一下节点类,节点类QTreeWidgetItem有很多构造函数,先来看其中的一个
QTreeWidgetItem(QTreeWidget *parent,const QStringList &strings,int type=Type);
注意第二个选项是QStringList而不是QString.
如果使用QString,则需要强制类型转换为QStringList
我们可以使用QTreeWidget的setHeaderLabels函数设置表头
例如
QTreeWidget treeWidget;
QStringList headers;
headers << "Name" << "Number";
treeWidget.setHeaderLabels(headers);
如果不想要表头,可以调用setHeaderHidden()将其隐藏.
group1->setFlags(Qt::ItemIsUserCheckable|Qt::ItemIsEnabled|Qt::ItemIsSelectable)
这里ItemIsUserCheckable如果没有这个选项,则树形框将不能选择,Qt::ItemIsEnabled 如果没有这个选项,树形框也将不能选择。Qt::ItemIsSelectable 这个不知道是干什么用的。
QTreeWidgetItem::setCheckState(int column,Qt::CheceState state)
设置这一列是否被选中
Qt::CheckState有三种状态
Qt::Unchecked
就是上边那种状态
Qt::Checked
Qt::PartiallyChecked
当节点状态改变时,使用节点改变信号itemChanged
connect(ui->treeWidget,SIGNAL(itemChanged(QTreeWidgetItem*,int)),this,SLOT(treeItemChanged(QTreeWidget*,int)));
然后编写treeItmeChanged(QTreeWidget*,int)槽函数。这个函数的作用是当树节点被选中时,子节点也全部被选中,当其中一个子节点被选中时,树节点会呈现部分被选中的状态。
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);
}
}
}
下面是如果选中的节点是子节点的处理
void Widget::updateParentItem(QTreeWidgetItem* item)
{
QTreeWidgetItem *parent = item->parent();//返回这个节点的父节点
if (parent == NULL)//如果没有父节点,返回
{
return;
}
//选中的子节点个数
int selectedCount = 0;//计算选中的个数
int childCount = parent->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);//如果选中的个数为0,则父节点也不选中
}
else if (selectedCount > 0 && selectedCount < childCount)//如果只选择了部分,则父节点的状态为部分选中
{
//部分选中状态
parent->setCheckState(0, Qt::PartiallyChecked);
}
else if (selectedCount == childCount)//如果全部选中,则父节点的状态为全部选中。
{
//未选中状态
parent->setCheckState(0, Qt::Checked);
}
}