相关资料:
https://blog.csdn.net/xdw_it/article/details/80973144
mainwindow.cpp
1 #include "mainwindow.h" 2 #include "ui_mainwindow.h" 3 4 MainWindow::MainWindow(QWidget *parent) 5 : QMainWindow(parent) 6 , ui(new Ui::MainWindow) 7 { 8 ui->setupUi(this); 9 setWindowTitle(QStringLiteral("QTreeView做出复选框功能")); 10 11 m_publicIconMap[QStringLiteral("treeItem_Project")] = QIcon(QStringLiteral(":/new/image/image/Project.png")); 12 m_publicIconMap[QStringLiteral("treeItem_folder")] = QIcon(QStringLiteral(":/new/image/image/folder.png")); 13 m_publicIconMap[QStringLiteral("treeItem_folder-ansys")] = QIcon(QStringLiteral(":/new/image/image/folder-ansys.png")); 14 m_publicIconMap[QStringLiteral("treeItem_group")] = QIcon(QStringLiteral(":/new/image/image/group.png")); 15 m_publicIconMap[QStringLiteral("treeItem_channel")] = QIcon(QStringLiteral(":/new/image/image/channel.png")); 16 17 QStandardItemModel* model = new QStandardItemModel(ui->treeView); 18 model->setHorizontalHeaderLabels(QStringList()<<QStringLiteral("项目名")<<QStringLiteral("信息")); 19 QStandardItem* itemProject = new QStandardItem(m_publicIconMap[QStringLiteral("treeItem_Project")],QStringLiteral("项目")); 20 model->appendRow(itemProject); 21 model->setItem(model->indexFromItem(itemProject).row(),1,new QStandardItem(QStringLiteral("项目信息说明"))); 22 QStandardItem* itemFolder = new QStandardItem(m_publicIconMap[QStringLiteral("treeItem_folder")],QStringLiteral("文件夹1")); 23 itemProject->appendRow(itemFolder); 24 itemProject->setChild(itemFolder->index().row(),1,new QStandardItem(QStringLiteral("信息说明"))); 25 itemFolder = new QStandardItem(m_publicIconMap[QStringLiteral("treeItem_folder")],QStringLiteral("文件夹2")); 26 itemProject->appendRow(itemFolder); 27 for(int i=0;i<5;++i) 28 { 29 QStandardItem* itemgroup = new QStandardItem(m_publicIconMap[QStringLiteral("treeItem_group")],QStringLiteral("组%1").arg(i+1)); 30 itemFolder->appendRow(itemgroup); 31 for(int j=0;j<(i+1);++j) 32 { 33 QStandardItem* itemchannel = new QStandardItem(m_publicIconMap[QStringLiteral("treeItem_channel")],QStringLiteral("频道%1").arg(j+1)); 34 itemgroup->appendRow(itemchannel); 35 itemgroup->setChild(itemchannel->index().row(),1,new QStandardItem(QStringLiteral("频道%1信息说明").arg(j+1))); 36 } 37 } 38 itemProject->setChild(itemFolder->index().row(),1,new QStandardItem(QStringLiteral("文件夹2信息说明"))); 39 itemProject = new QStandardItem(m_publicIconMap[QStringLiteral("treeItem_Project")],QStringLiteral("项目2")); 40 itemProject->setCheckable(true); 41 itemProject->setTristate(true); 42 model->appendRow(itemProject); 43 for(int i =0;i<3;++i) 44 { 45 itemFolder = new QStandardItem(m_publicIconMap[QStringLiteral("treeItem_folder")],QStringLiteral("项目2文件夹%1").arg(i+1)); 46 itemFolder->setCheckable(true); 47 itemFolder->setTristate(true); 48 QStandardItem* itemFolderDes = new QStandardItem(m_publicIconMap[QStringLiteral("treeItem_group")],QStringLiteral("文件夹%1组").arg(i+1)); 49 itemProject->appendRow(itemFolder); 50 itemProject->setChild(itemFolder->index().row(),1,itemFolderDes); 51 for(int j=0;j<i+1;++j) 52 { 53 QStandardItem* item = new QStandardItem(m_publicIconMap[QStringLiteral("treeItem_dataItem")],QStringLiteral("项目%1").arg(j+1)); 54 item->setCheckable(true); 55 itemFolder->appendRow(item); 56 } 57 } 58 //关联项目属性改变的信号和槽 59 connect(model,&QStandardItemModel::itemChanged,this,&::MainWindow::on_treeItemChanged); 60 //connect(model,SIGNAL(itemChanged(QStandardItem*)),this,SLOT(treeItemChanged(QStandardItem*))); 61 ui->treeView->setModel(model); 62 } 63 64 MainWindow::~MainWindow() 65 { 66 delete ui; 67 } 68 69 void MainWindow::on_treeView_clicked(const QModelIndex &index) 70 { 71 QString sData; 72 QString sDir; 73 QString sfilePath; 74 QString stype; 75 QString sfileName; 76 QString sFromatStr = QStringLiteral("data:%1 \nisDir:%2 \nfilePath:%3 \ntype:%4 \nfileName:%5"); 77 sData = index.data().toString(); 78 // sDir = QString::number(m_pFileModel->isDir(index)); 79 // sfilePath = m_pFileModel->filePath(index); 80 // stype = m_pFileModel->type(index); 81 // sfileName = m_pFileModel->fileName(index); 82 83 ui->textEdit->setText(""); 84 ui->textEdit->append(sFromatStr.arg(sData).arg(sDir).arg(sfilePath).arg(stype).arg(sfileName)); 85 } 86 87 // brief 测量兄弟节点的情况,如果都选中返回Qt::Checked,都不选中Qt::Unchecked,不完全选中返回Qt::PartiallyChecked 88 // param item 89 // return 如果都选中返回Qt::Checked,都不选中Qt::Unchecked,不完全选中返回Qt::PartiallyChecked 90 Qt::CheckState MainWindow::checkSibling(QStandardItem * item) 91 { 92 //先通过父节点获取兄弟节点 93 QStandardItem * parent = item->parent(); 94 if(nullptr == parent) 95 return item->checkState(); 96 int brotherCount = parent->rowCount(); 97 int checkedCount(0),unCheckedCount(0); 98 Qt::CheckState state; 99 for(int i=0;i<brotherCount;++i) 100 { 101 QStandardItem* siblingItem = parent->child(i); 102 state = siblingItem->checkState(); 103 if(Qt::PartiallyChecked == state) 104 return Qt::PartiallyChecked; 105 else if(Qt::Unchecked == state) 106 ++unCheckedCount; 107 else 108 ++checkedCount; 109 if(checkedCount>0 && unCheckedCount>0) 110 return Qt::PartiallyChecked; 111 } 112 if(unCheckedCount>0) 113 return Qt::Unchecked; 114 return Qt::Checked; 115 } 116 117 void MainWindow::on_treeItemChanged(QStandardItem * item) 118 { 119 qDebug() << "on_treeItemChanged"; 120 121 if ( item == nullptr ) 122 return ; 123 if ( item->isCheckable ()) 124 { 125 //如果条目是存在复选框的,那么就进行下面的操作 126 Qt::CheckState state = item->checkState(); //获取当前的选择状态 127 if (item->isTristate()) 128 { 129 //如果条目是三态的,说明可以对子目录进行全选和全不选的设置 130 if ( state != Qt::PartiallyChecked ) 131 { 132 //当前是选中状态,需要对其子项目进行全选 133 treeItem_checkAllChild ( item , state == Qt::Checked ? true : false ); 134 } 135 } 136 else 137 { 138 //说明是两态的,两态会对父级的三态有影响 139 //判断兄弟节点的情况 140 treeItem_CheckChildChanged(item); 141 } 142 } 143 } 144 145 // brief 根据子节点的改变,更改父节点的选择情况 146 // param item 147 void MainWindow::treeItem_CheckChildChanged(QStandardItem * item) 148 { 149 if(nullptr == item) 150 return; 151 Qt::CheckState siblingState = checkSibling(item); 152 QStandardItem * parentItem = item->parent(); 153 if(nullptr == parentItem) 154 return; 155 if(Qt::PartiallyChecked == siblingState) 156 { 157 if(parentItem->isCheckable() && parentItem->isTristate()) 158 parentItem->setCheckState(Qt::PartiallyChecked); 159 } 160 else if(Qt::Checked == siblingState) 161 { 162 if(parentItem->isCheckable()) 163 parentItem->setCheckState(Qt::Checked); 164 } 165 else 166 { 167 if(parentItem->isCheckable()) 168 parentItem->setCheckState(Qt::Unchecked); 169 } 170 treeItem_CheckChildChanged(parentItem); 171 } 172 173 // brief 递归设置所有的子项目为全选或全不选状态 174 // param item 当前项目 175 // param check true时为全选,false时全不选 176 void MainWindow::treeItem_checkAllChild(QStandardItem *item, bool check) 177 { 178 if(item == nullptr) 179 return; 180 int rowCount = item->rowCount(); 181 for(int i=0;i<rowCount;++i) 182 { 183 QStandardItem* childItems = item->child(i); 184 treeItem_checkAllChild_recursion(childItems,check); 185 } 186 if(item->isCheckable()) 187 item->setCheckState(check ? Qt::Checked : Qt::Unchecked); 188 } 189 190 void MainWindow::treeItem_checkAllChild_recursion(QStandardItem * item,bool check) 191 { 192 if(item == nullptr) 193 return; 194 int rowCount = item->rowCount(); 195 for(int i=0;i<rowCount;++i) 196 { 197 QStandardItem* childItems = item->child(i); 198 treeItem_checkAllChild_recursion(childItems,check); 199 } 200 if(item->isCheckable()) 201 item->setCheckState(check ? Qt::Checked : Qt::Unchecked); 202 }View Code