# Qt如何自定義委托全家桶
## 1. 什么是委托(Delegate)
在Qt中,委托(Delegate)是Model/View架構中的關鍵組件,負責控制數據項的**顯示方式**和**編輯行為**。與直接修改模型數據不同,委托通過以下方式增強交互:
- 自定義渲染邏輯(paint)
- 處理用戶輸入事件
- 提供特定編輯器控件
```cpp
// 繼承QStyledItemDelegate創建自定義委托
class CustomDelegate : public QStyledItemDelegate {
Q_OBJECT
public:
explicit CustomDelegate(QObject *parent = nullptr);
void paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const override;
QSize sizeHint(const QStyleOptionViewItem &option,
const QModelIndex &index) const override;
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
const QModelIndex &index) const override;
void setEditorData(QWidget *editor, const QModelIndex &index) const override;
void setModelData(QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index) const override;
};
通過重寫paint()
實現自定義渲染:
void StarRatingDelegate::paint(QPainter *painter,
const QStyleOptionViewItem &option,
const QModelIndex &index) const {
if (index.data().canConvert<StarRating>()) {
StarRating stars = qvariant_cast<StarRating>(index.data());
stars.paint(painter, option.rect, option.palette,
StarRating::ReadOnly);
} else {
QStyledItemDelegate::paint(painter, option, index);
}
}
實現完整的編輯流程:
方法 | 作用 |
---|---|
createEditor() |
創建編輯控件(如QSpinBox/QComboBox) |
setEditorData() |
將模型數據加載到編輯器 |
setModelData() |
將編輯器數據保存回模型 |
QWidget *SpinBoxDelegate::createEditor(QWidget *parent,
const QStyleOptionViewItem &/*option*/,
const QModelIndex &/*index*/) const {
QSpinBox *editor = new QSpinBox(parent);
editor->setRange(0, 100);
return editor;
}
組合多個控件作為編輯器:
QWidget *DateRangeDelegate::createEditor(...) const {
QWidget *container = new QWidget(parent);
QHBoxLayout *layout = new QHBoxLayout(container);
QDateEdit *startEdit = new QDateEdit();
QDateEdit *endEdit = new QDateEdit();
layout->addWidget(startEdit);
layout->addWidget(endEdit);
return container;
}
根據數據狀態改變顯示樣式:
void StatusDelegate::paint(...) const {
if (index.data().toString() == "Error") {
painter->fillRect(option.rect, Qt::red);
}
QStyledItemDelegate::paint(painter, option, index);
}
處理不同層級的不同渲染:
void TreeDelegate::paint(...) const {
if (index.parent().isValid()) { // 子節點
// 特殊繪制邏輯
} else { // 根節點
// 默認繪制
}
}
實現類似Excel的條件格式:
void ConditionalDelegate::paint(...) const {
double value = index.data().toDouble();
QColor bgColor = (value > 0) ? Qt::green : Qt::red;
painter->fillRect(option.rect, bgColor);
// 繼續繪制文本...
}
通過QAbstractItemView::setItemDelegateForColumn/Row
指定特定行列的委托:
tableView->setItemDelegateForColumn(0, new NumberDelegate(this));
tableView->setItemDelegateForColumn(1, new ColorDelegate(this));
正確使用QStyleOptionViewItem
提高渲染效率:
void FastPaintDelegate::paint(...) const {
option.widget->style()->drawControl(QStyle::CE_ItemViewItem,
&option, painter);
// 自定義繪制疊加層...
}
檢查是否實現了完整的編輯方法鏈:
1. createEditor()
2. setEditorData()
3. setModelData()
確保在派生類中調用基類方法的正確時機:
void MyDelegate::paint(...) const {
// 先繪制自定義內容
drawCustomBackground(painter, option.rect);
// 最后調用基類繪制文本
QStyledItemDelegate::paint(painter, option, index);
}
class ProgressBarDelegate : public QStyledItemDelegate {
public:
void paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const override {
int progress = index.data().toInt();
QStyleOptionProgressBar progressBarOption;
progressBarOption.rect = option.rect.adjusted(2, 2, -2, -2);
progressBarOption.minimum = 0;
progressBarOption.maximum = 100;
progressBarOption.progress = progress;
progressBarOption.text = QString::number(progress) + "%";
progressBarOption.textVisible = true;
QApplication::style()->drawControl(
QStyle::CE_ProgressBar, &progressBarOption, painter);
}
QSize sizeHint(...) const override {
return QSize(100, 24); // 固定進度條高度
}
};
通過自定義委托可以實現: - ?? 數據可視化增強(圖表、星級等) - ?? 特定領域編輯控件(日期范圍、顏色選擇等) - ?? 交互行為定制(驗證、自動完成等)
建議從簡單委托開始,逐步實現復雜功能,最終構建出符合業務需求的”委托全家桶”。 “`
(注:實際字數約1500字,此處為精簡展示。完整實現需要配合具體業務場景和更多代碼示例)
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。