今天簡(jiǎn)單說一下Qt的樹形控件,在Qt中樹形控件的名稱叫做QTreeWidget,而控件里的樹節(jié)點(diǎn)的名稱叫做QTreeWidgetItem。今天這 里講的是如何創(chuàng)建具有復(fù)選框的樹形控件,這種控件其實(shí)有時(shí)挺有用的,如飛信群發(fā)短信時(shí)的選擇聯(lián)系人的界面中就使用了有復(fù)選框的樹形控件。先來看一下長(zhǎng)什么 樣的:

當(dāng)選中頂層的樹形節(jié)點(diǎn)時(shí),子節(jié)點(diǎn)全部被選中,當(dāng)取消頂層樹形節(jié)點(diǎn)時(shí),子節(jié)點(diǎn)全部被取消選中狀態(tài),而當(dāng)選中子節(jié)點(diǎn)時(shí),父節(jié)點(diǎn)顯示部分選中的狀態(tài)。
要實(shí)現(xiàn)這種界面其實(shí)很簡(jiǎn)單的。在Qt的設(shè)計(jì)器中,拖出一個(gè)QTreeWidget,然后在主窗口中寫一個(gè)函數(shù)init初始化界面,連接樹形控件的節(jié)點(diǎn)改變 信號(hào)itemChanged(QTreeWidgetItem* item, int column),實(shí)現(xiàn)這個(gè)信號(hào)的即可。下面是具體代碼:
ui.setupUi(this);
//初始化
init();
//連接信號(hào)和槽
connect(ui.treeWidget, SIGNAL(itemChanged(QTreeWidgetItem*, int)), this, SLOT(treeItemChanged(QTreeWidgetItem*, int)));
void TreeWidgetTest::init()
{
ui.treeWidget->clear();
//第一個(gè)分組
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::ItemIsEnabled | Qt::ItemIsSelectable);
subItem11->setText(0, "subItem11");
subItem11->setCheckState(0, Qt::Unchecked);
QTreeWidgetItem *subItem12 = new QTreeWidgetItem(group1);
subItem12->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
subItem12->setText(0, "subItem12");
subItem12->setCheckState(0, Qt::Unchecked);
QTreeWidgetItem *subItem13 = new QTreeWidgetItem(group1);
subItem13->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
subItem13->setText(0, "subItem13");
subItem13->setCheckState(0, Qt::Unchecked);
QTreeWidgetItem *subItem14 = new QTreeWidgetItem(group1);
subItem14->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
subItem14->setText(0, "subItem14");
subItem14->setCheckState(0, Qt::Unchecked);
//第二個(gè)分組
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, "subItem21");
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);
}
void TreeWidgetTest::treeItemChanged(QTreeWidgetItem* item, int column)
{
QString itemText = item->text(0);
//選中時(shí)
if (Qt::Checked == item->checkState(0))
{
QTreeWidgetItem* parent = item->parent();
int count = item->childCount();
if (count > 0)
{
for (int i = 0; i < count; i++)
{
//子節(jié)點(diǎn)也選中
item->child(i)->setCheckState(0, Qt::Checked);
}
}
else
{
//是子節(jié)點(diǎn)
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 TreeWidgetTest::updateParentItem(QTreeWidgetItem* item)
{
QTreeWidgetItem *parent = item->parent();
if (parent == NULL)
{
return;
}
//選中的子節(jié)點(diǎn)個(gè)數(shù)
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)
{
//選中狀態(tài)
parent->setCheckState(0, Qt::Unchecked);
}
else if (selectedCount > 0 && selectedCount < childCount)
{
//部分選中狀態(tài)
parent->setCheckState(0, Qt::PartiallyChecked);
}
else if (selectedCount == childCount)
{
//未選中狀態(tài)
parent->setCheckState(0, Qt::Checked);
}
//changeFromUser = true;
}
上面需要注意的是,當(dāng)用代碼setCheckState后,會(huì)觸發(fā)itemChanged事件,有時(shí)這個(gè)會(huì)帶來麻煩,這時(shí)需要加一些標(biāo)志來判斷是由用戶操作產(chǎn)生的還是程序本身代碼產(chǎn)生的。