QTreeWidget复选框checkbox使⽤
使⽤QTreewidget时,⽤到复选框。还有⼀个苛刻的要求,即在选中或取消选中时,还要做⼀些操作。刚开始参考了⽹上的⼀些⽅法,参考了,使⽤itemChange(QTreeWidgetItem*,int)信号,可以实现,但是不满⾜我个⼈的需求:我在点选时,要在事件中做其他操作,⽽每个节点的checkbox状态改变时,itemChange都会被触发,如我的例⼦中,我选中⽬标1时,⽬标1的所有⼦节点会被选中,如果有3个⼦节点,⼀共会触发3+1次itemChange,这不是我想看到的。所以,我尝试使⽤另⼀种⽅法,期望满⾜条件。 本⽂只是在学习的层⾯讨论,不讨论⽅法优劣。时刻抱持实⽤主义的观点,不管⽩猫⿊猫,只要捉住⽼⿏就是好猫。 头⽂件:
a70751 #ifndef MYDLG_H
2#define MYDLG_H
3
4 #include <QDialog>
5 #include <QTreeWidget>
6 #include <map>
7using namespace std;
8
9namespace Ui {
10class MyDlg;
11 }
12
13class MyDlg : public QDialog
14 {
15 Q_OBJECT
16
17public:
18explicit MyDlg(QWidget *parent = 0);
19 ~MyDlg();
20
21private slots:
22void on_btnQuit_clicked();
23void TreeItemClicked(QTreeWidgetItem* item, int col);
24private:
25 Ui::MyDlg *ui;
26 map<QTreeWidgetItem*, Qt::CheckState> m_mapItemState;
27
28
29void InitTree();//初始化
30//添加节点
31 QTreeWidgetItem* AddTreeItem(QTreeWidget* pTree, QTreeWidgetItem* parentItem, QString itemTxt);
32//获取当前的所有checkbox状态,和选中的节点
33void GetCheckItem(QTreeWidget* pTree, QList<QString>& listTarget);
34void ChangeChildItemState(QTreeWidgetItem* thisItem);//根据点击的节点,来改变节点的⼦节点状态
35void ChangeParentItemState(QTreeWidgetItem* thisItem);//根据点击的节点,来改变节点的⽗节点状态
36//获取节点的上次状态
37 Qt::CheckState GetItemState(QTreeWidgetItem* item, map<QTreeWidgetItem*, Qt::CheckState>& mapItemState);
38
39 };
40
41#endif// MYDIALOG_H
源⽂件:
1 #include "MyDlg.h"
2 #include "ui_MyDlg.h"
3 #include <QDebug>
4
5 MyDlg::MyDlg(QWidget *parent) :
6 QDialog(parent),
7 ui(new Ui::MyDlg)
8 {
9 ui->setupUi(this);
10 InitTree();
11
12//⾸次获得节点状态
13 QList<QString> list;
14 GetCheckItem(ui->treeWidget, list);
15 }
16
17 MyDlg::~MyDlg()
18 {
19delete ui;
20 }
21
22void MyDlg::on_btnQuit_clicked()
23 {
24
25 }
26
27void MyDlg::TreeItemClicked(QTreeWidgetItem *item, int col)
28 {
29if(item->checkState(0) == GetItemState(item, m_mapItemState))//item状态是否改变
30return;
31 ChangeChildItemState(item);
32 ChangeParentItemState(item);
33 QList<QString> listTarget;
34 GetCheckItem(ui->treeWidget, listTarget);
35 qDebug() << listTarget;
36
37 }
38
39void MyDlg::InitTree()
40 {
41 connect(ui->treeWidget, SIGNAL(itemClicked(QTreeWidgetItem*,int)), this, SLOT(TreeItemClicked(QTreeWidgetItem*,int)));
42 ui->treeWidget->header()->setHidden(1);
43 QTreeWidgetItem* topItem = new QTreeWidgetItem;
44 topItem->setCheckState(0, Qt::Unchecked);
45 topItem->setText(0, "⽬标列表");
46 ui->treeWidget->addTopLevelItem(topItem);
47 QTreeWidgetItem* item1 = AddTreeItem(ui->treeWidget, topItem, "⽬标1");
48 QList<QString> listTarget;
49 listTarget << "⽬标11" << "⽬标12";
50for(int i = 0; i < unt(); i++){
51 AddTreeItem(ui->treeWidget, item1, listTarget.at(i));
52 }
53
54 QTreeWidgetItem* item2 = AddTreeItem(ui->treeWidget, topItem, "⽬标2");
55 listTarget.clear();
56 listTarget << "⽬标21" << "⽬标22" << "⽬标23";
57for(int i = 0; i < unt(); i++){
58 AddTreeItem(ui->treeWidget, item2, listTarget.at(i));
59 }
60
61 QTreeWidgetItem* item3 = AddTreeItem(ui->treeWidget, topItem, "⽬标3");
62 listTarget.clear();
63 listTarget << "⽬标31" << "⽬标32" << "⽬标33" << "⽬标34";
64for(int i = 0; i < unt(); i++){
65 AddTreeItem(ui->treeWidget, item3, listTarget.at(i));
66 }
67
68 ui->treeWidget->expandAll();
筋膜仪69 }
70
71 QTreeWidgetItem *MyDlg::AddTreeItem(QTreeWidget *pTree, QTreeWidgetItem *parentItem, QString itemTxt)
72 {
73 QTreeWidgetItem *item = new QTreeWidgetItem(parentItem);
74 item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
75 item->setCheckState(0, Qt::Unchecked);
76 item->setText(0, itemTxt);
77return item;
78 }
79
80void MyDlg::GetCheckItem(QTreeWidget *pTree, QList<QString> &listTarget)
81 {//这个本来是为了获取选中的节点⽂本。后来增加了获取所有节点的状态,以备将来判断节点状态是否改变
82 m_mapItemState.clear();
83
84 QTreeWidgetItemIterator it(pTree);
85while (*it) {
86if((*it)->checkState(0) == Qt::Checked){
87 QString itemTxt = (*it)->text(0);
88if(itemTxtpare("") != 0){
89 listTarget.push_back(itemTxt);
90 }
91 }
92 m_mapItemState[(*it)] = (*it)->checkState(0);
93 ++it;
94 }
95 }
96 //遍历该节点下所有⼦节点
97void MyDlg::ChangeChildItemState(QTreeWidgetItem *thisItem)
98 {
99int nChildCount = thisItem->childCount();
100if(nChildCount < 1) return;
101
102for(int i = 0; i < nChildCount; i++){
103 thisItem->child(i)->setCheckState(0, thisItem->checkState(0));
104 ChangeChildItemState(thisItem->child(i));
105 }
106 }
107
108void MyDlg::ChangeParentItemState(QTreeWidgetItem *thisItem)
109 {
110 QTreeWidgetItem* parentItem = thisItem->parent();
111if(parentItem == NULL) return;
112
113int nChildCount = parentItem->childCount();
114int nSelected = 0;
115int nPartSelected = 0;
116for(int i = 0; i < nChildCount; i++){
117if(parentItem->child(i)->checkState(0) == Qt::Checked){
118 nSelected++;
119 }
120else if(parentItem->child(i)->checkState(0) == Qt::PartiallyChecked){
121 nPartSelected++;
122 }
123 }
124 //如果该节点有⼦节点被选中,但选中的节点个数⼩于⼦节点数,或者有⼦节点是半选中状态,则该节点为半选中
小样机125if((nSelected > 0 && nSelected < nChildCount) || nPartSelected > 0){
126 parentItem->setCheckState(0, Qt::PartiallyChecked);
127 }
128else if(nSelected == nChildCount){
129 parentItem->setCheckState(0, Qt::Checked);
蝇蛆蛋白
130 }
131else {
132 parentItem->setCheckState(0, Qt::Unchecked);
133 }彩灯控制电路
134 ChangeParentItemState(parentItem);
135 }
136
137 Qt::CheckState MyDlg::GetItemState(QTreeWidgetItem *item, map<QTreeWidgetItem *, Qt::CheckState> &mapItemState) 138 {
139 map<QTreeWidgetItem*, Qt::CheckState>::iterator iter = m_mapItemState.find(item);
140if(iter != d()){
141return iter->second;
142 }
143return Qt::Unchecked;
144 }
ui⽂件:
1 <?xml version="1.0" encoding="UTF-8"?>
2 <ui version="4.0">
3 <class>MyDlg</class>
4 <widget class="QDialog" name="MyDlg">
5 <property name="geometry">
6 <rect>
7 <x>0</x>
8 <y>0</y>
9 <width>400</width>
10 <height>300</height>
11 </rect>
12 </property>
13 <property name="windowTitle">
14 <string>Dialog</string>
15 </property>
16 <layout class="QGridLayout" name="gridLayout">
17 <item row="0" column="0" colspan="2">
18 <widget class="QTreeWidget" name="treeWidget">
19 <column>
20 <property name="text">
21 <string notr="true">1</string>
22 </property>
23 </column>
24 </widget>
25 </item>
26 <item row="1" column="0">
27 <spacer name="horizontalSpacer">
28 <property name="orientation">
29 <enum>Qt::Horizontal</enum>
30 </property>
31 <property name="sizeHint" stdset="0">
32 <size>
33 <width>298</width>眼镜清洗剂
34 <height>20</height>
35 </size>
36 </property>
37 </spacer>
38 </item>
39 <item row="1" column="1">
40 <widget class="QPushButton" name="btnQuit">
41 <property name="text">
42 <string>quit</string>
43 </property>
44 </widget>
45 </item>
46 </layout>
47 </widget>
48 <resources/>
49 <connections/>
50 </ui>