相關資料:
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 }