前言
QTableWidget表頭不能直接設置復選框,setCheckState不適用,所以直接使用設置圖片的方法最方便快捷,準備兩個圖片,分別為選中狀態和未選中狀態。
1.設置復選框列
設置第一列為復選框列,其他列正常顯示內容:
for (int j = 0; j < table_head.size(); ++j)
{if (j == 0)//全選列 {//不直接設置setCellWidget為QCheckBox,使用布局再添加可使復選框居中QCheckBox *pCheckBox = new QCheckBox();pCheckBox->setCheckState(Qt::Unchecked);QWidget *pWgt = new QWidget;QVBoxLayout *pLayout = new QVBoxLayout;pLayout->addWidget(pCheckBox);pWgt->setLayout(pLayout);//設置margin,使復選框列窄一點,默認寬度比較大pCheckBox->setContentsMargins(0, 0, 0, 0);pLayout->setMargin(2);tableWidget->setCellWidget(i, j, pWgt);}else {QTableWidgetItem * pItem;pItem = new QTableWidgetItem;pItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);pItem->setTextAlignment(Qt::AlignCenter);tableWidget->setItem(i, j, pItem);tableWidget->setText("abc");}
}
?2.設置表頭圖片與樣式
直接添加Icon,默認會緊貼表格的左側,并不居中,非常不好看。
所以使用setStyleSheet設置表頭樣式,如果使用QHeaderView::section是默認對所以表頭設置樣式,所以在設置樣式時使用QHeaderView::section:first,只設置第一列左邊距為6,這是我測試出比較合適的寬度。
設置表頭全選框圖片時,仍然可以拖動列寬,我不希望第一列可以拖動,因為沒有意義,所以設置horizontalHeader為QHeaderView::Fixed模式,不允許拖動列寬。
這樣就是比較美觀的表格了。
//添加全選
tableWidget->horizontalHeaderItem(0)->setIcon(QIcon(":/Resources/res/icon/uncheck.png"));
//表頭第一列圖片左邊距設置為6
tableWidget->horizontalHeader()->setStyleSheet("QHeaderView::section:first { padding-left: 6px; }");
tableWidget->horizontalHeader()->resizeSections(QHeaderView::ResizeToContents);
//設置第一列不能拖動,為固定寬度
tableWidget->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Fixed);
3.全選響應事件
對表頭進行點擊事件響應,使用sectionClicked信號。
connect(tableWidget->horizontalHeader(), &QHeaderView::sectionClicked, this, & Test::slot_onHeaderClicked);
void Test::slot_onHeaderClicked(int logicalIndex)
{if (logicalIndex != 0){return;}QString strText = tableWidget->horizontalHeaderItem(0)->text();//m_bChecked用來對表頭全選圖片進行設置if (!m_bChecked){m_bChecked = true;tableWidget->horizontalHeaderItem(0)->setIcon(QIcon(":/Resources/res/icon/checked.png"));}else{m_bChecked = false;tableWidget->horizontalHeaderItem(0)->setIcon(QIcon(":/Resources/res/icon/uncheck.png"));}//全選int nRow = tableWidget->rowCount();for (int i = 0; i < nRow; i++){QCheckBox *pCheckBox = getCheckBox(i);//獲取第一列中的復選框if (pCheckBox == nullptr){continue;}if (m_bChecked){pCheckBox->setChecked(true);}else{pCheckBox->setChecked(false);}}}
4.第一列選擇框,勾選響應事件
需求:
(1)單選時,當前列多選框勾選
(2)鼠標左鍵按下時拖拽,可選多行
設置表格為多選模式:
tableWidget->setSelectionMode(QAbstractItemView::ExtendedSelection);
實現的信號:
connect(tableWidget, &QTableWidget::itemSelectionChanged, this, &Test::slot_checkStates);
實現:
void Test::slot_checkStates()
{int curiRow = tableWidget->currentRow();//獲取勾選框QCheckBox *pCheckBox = getCellCheckBox(curiRow);if (pCheckBox == nullptr){return;}if (pCheckBox->isChecked())pCheckBox->setChecked(false);elsepCheckBox->setChecked(false);tableWidget->horizontalHeaderItem(0)->setIcon(QIcon(":/Resources/res/icon//uncheck.png"));m_bChecked = false;QList<QTableWidgetItem*> lstSelectedItems = tableWidget->selectedItems();QList<int> lstSelectedRow;for (int i = 0; i < lstSelectedItems.size(); i++){if (lstSelectedItems.at(i) == nullptr){continue;}int nRow = lstSelectedItems.at(i)->row();if (!lstSelectedRow.contains(nRow)){lstSelectedRow << nRow;}}for (int m = 0; m < tableWidget->rowCount(); m++){QCheckBox *pTmpCheckBox = getCellCheckBox(m);if (pTmpCheckBox == nullptr){continue;}//設置選中,異或,只符合一個條件才行if ((lstSelectedRow.size() > 0 && lstSelectedRow.contains(m)) ^ (lstSelectedRow.size() == 0 && m == curiRow)){pTmpCheckBox->setChecked(true);continue;}pTmpCheckBox->setChecked(false);}
}