目錄
- 方法一:QSS
- 方法2:自定義復選框委托類
- 一、構造函數 `CheckBoxDelegate()`
- 二、`paint()` 方法
- 三、`editorEvent()` 方法
- 四、關鍵設計要點
- 五、擴展應用場景
- 六、代碼示例(補充)
方法一:QSS
QTableView::indicator {position: relative; /* 相對定位 */left: 50%; /* 左邊線定位到父容器中心 */
}
缺點:需要計算向右移動一定距離的left
position和left的QSS解釋
方法2:自定義復選框委托類
#include <QApplication>
#include <QTableView>
#include <QStandardItemModel>
#include <QStyledItemDelegate>
#include <QPainter>
#include <QStyleOptionButton>
#include <QMouseEvent>// 自定義復選框委托類
// 功能:實現在 QTableView 中居中顯示復選框,并支持點擊交互,結合原樣式
class CheckBoxDelegate : public QStyledItemDelegate {
public:// 構造函數explicit CheckBoxDelegate(QObject* parent = nullptr): QStyledItemDelegate(parent) {} // 繼承基類構造函數// 重寫繪制方法void paint(QPainter* painter,const QStyleOptionViewItem& option,const QModelIndex& index) const override{// 檢查當前項是否支持勾選(Qt::ItemIsUserCheckable 標志)if (index.flags() & Qt::ItemIsUserCheckable){// --- 步驟 1: 準備繪制參數 ---QStyleOptionButton checkOption; // 創建復選框的樣式選項checkOption.rect = option.rect; // 初始矩形區域設為單元格區域checkOption.state = option.state; // 繼承基礎狀態(如啟用、激活狀態)// 獲取當前項的勾選狀態Qt::CheckState checkState = static_cast<Qt::CheckState>(index.data(Qt::CheckStateRole).toInt());// 根據狀態設置 QStyle 標志if (checkState == Qt::Checked) {checkOption.state |= QStyle::State_On; // 選中狀態}else {checkOption.state |= QStyle::State_Off; // 未選中狀態}// --- 步驟 2: 計算居中位置 ---// 獲取標準復選框指示器的默認尺寸(例如 16x16)QRect checkRect = option.widget->style()->subElementRect(QStyle::SE_CheckBoxIndicator, // 獲取復選框指示器區域&checkOption, // 傳入樣式選項option.widget // 關聯的控件(用于樣式計算));// 將復選框矩形中心對齊到單元格中心checkRect.moveCenter(option.rect.center());checkOption.rect = checkRect; // 更新樣式選項中的矩形區域// --- 步驟 3: 繪制復選框 ---// 使用當前控件的樣式繪制復選框option.widget->style()->drawPrimitive(QStyle::PE_IndicatorCheckBox, // 繪制復選框基本元素&checkOption, // 樣式選項painter, // 畫布option.widget // 關聯的控件(用于樣式適配));}else{// 對于非勾選項,調用基類默認繪制方法(例如文本、背景等)QStyledItemDelegate::paint(painter, option, index);}}// 重寫事件處理方法(實現點擊交互)bool editorEvent(QEvent* event,QAbstractItemModel* model,const QStyleOptionViewItem& option,const QModelIndex& index) override{// 只處理鼠標釋放事件(點擊完成時觸發)if (event->type() == QEvent::MouseButtonRelease){QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);// --- 步驟 1: 計算復選框的實際點擊區域 ---QStyleOptionButton checkOption;checkOption.rect = option.rect; // 初始區域為單元格區域// 獲取標準復選框指示器的矩形(與繪制時計算方式一致)QRect checkRect = option.widget->style()->subElementRect(QStyle::SE_CheckBoxIndicator,&checkOption,option.widget);// 將矩形中心對齊到單元格中心(確保與繪制的區域一致)checkRect.moveCenter(option.rect.center());// --- 步驟 2: 判斷點擊是否在復選框區域內 ---if (checkRect.contains(mouseEvent->pos())){// 獲取當前勾選狀態Qt::CheckState currentState = static_cast<Qt::CheckState>(index.data(Qt::CheckStateRole).toInt());// 切換狀態(Checked <-> Unchecked)Qt::CheckState newState = (currentState == Qt::Checked)? Qt::Unchecked: Qt::Checked;// 更新模型數據(觸發視圖刷新)model->setData(index, newState, Qt::CheckStateRole);return true; // 事件已處理,不再傳遞}}// 其他事件交由基類處理(例如鍵盤事件、未點擊復選框區域的鼠標事件)return QStyledItemDelegate::editorEvent(event, model, option, index);}
};
在 Qt 的 QTableView
中,通過自定義委托類 CheckBoxDelegate
實現復選框居中顯示和交互功能,其核心邏輯集中在 paint()
和 editorEvent()
方法中。
一、構造函數 CheckBoxDelegate()
功能:
繼承自 QStyledItemDelegate
并初始化父類,為后續的委托操作提供基礎支持。
代碼解析:
explicit CheckBoxDelegate(QObject* parent = nullptr): QStyledItemDelegate(parent) {}
- 作用:通過基類構造函數傳遞父對象指針,確保委托與視圖控件的生命周期綁定。
二、paint()
方法
核心功能:
負責繪制居中顯示的復選框,并根據模型數據狀態(選中/未選中)更新樣式。
關鍵步驟解析:
-
檢查可勾選性
通過index.flags() & Qt::ItemIsUserCheckable
判斷當前項是否支持勾選,避免對非勾選項誤操作。 -
準備繪制參數
- 樣式選項初始化:創建
QStyleOptionButton
對象,繼承視圖的基礎狀態(如控件是否啟用)。 - 狀態設置:根據模型的
Qt::CheckStateRole
數據設置QStyle::State_On
(選中)或QStyle::State_Off
(未選中)標志。
- 樣式選項初始化:創建
-
計算居中位置
QRect checkRect = option.widget->style()->subElementRect(QStyle::SE_CheckBoxIndicator, &checkOption, option.widget ); checkRect.moveCenter(option.rect.center());
- 子元素矩形獲取:通過
QStyle::SE_CheckBoxIndicator
獲取默認復選框指示器的尺寸(如 16x16)。 - 中心對齊:將矩形中心對齊到單元格中心,確保復選框居中。
- 子元素矩形獲取:通過
-
繪制復選框
調用QStyle::drawPrimitive()
方法,使用當前控件的樣式(如 Fusion、Windows 等)繪制復選框。
三、editorEvent()
方法
核心功能:
處理鼠標點擊事件,實現復選框狀態的切換與模型數據更新。
關鍵步驟解析:
-
事件類型過濾
僅處理QEvent::MouseButtonRelease
事件,確保在鼠標釋放時觸發狀態切換。 -
點擊區域計算
QRect checkRect = option.widget->style()->subElementRect(QStyle::SE_CheckBoxIndicator, &checkOption, option.widget ); checkRect.moveCenter(option.rect.center());
- 與繪制邏輯一致:使用相同的子元素矩形計算方法,確保點擊區域與繪制區域完全匹配。
-
狀態切換與模型更新
- 獲取當前狀態:從模型數據中讀取
Qt::CheckStateRole
的值。 - 狀態取反:切換選中(
Qt::Checked
)與未選中(Qt::Unchecked
)狀態。 - 更新模型:通過
model->setData()
修改數據,觸發視圖刷新。
- 獲取當前狀態:從模型數據中讀取
四、關鍵設計要點
-
樣式一致性
使用QStyle
繪制復選框,確保與當前系統或應用程序主題兼容。 -
交互精準性
通過計算點擊區域與繪制區域的一致性,避免誤觸或點擊無效的問題。 -
性能優化
- 避免重復計算:僅在需要時處理勾選項的繪制和事件。
- 模型-視圖分離:通過
setData()
更新模型,符合 Qt 的模型/視圖架構。
五、擴展應用場景
-
三態復選框
可擴展支持Qt::PartiallyChecked
狀態,用于樹形表格的父子節點聯動。 -
動態樣式調整
結合QSS
修改復選框顏色、尺寸,或通過重寫sizeHint()
調整單元格大小。 -
鍵盤事件支持
在editorEvent()
中處理QEvent::KeyPress
,支持空格鍵切換復選框狀態。
六、代碼示例(補充)
// 在 QTableView 中應用委托
QTableView *tableView = new QTableView();
CheckBoxDelegate *delegate = new CheckBoxDelegate(tableView );
tableView->setItemDelegate(delegate); // 對所有列生效
或者
// 在 QTableView 中應用委托
QTableView *tableView = new QTableView();
CheckBoxDelegate *delegate = new CheckBoxDelegate(tableView );
tableView->setItemDelegateForColumn(0, delegate); // 對第 0 列生效