【Qt】自定义委托(Delegate)的核心方法
在 Qt 的模型/视图框架中,自定义委托(Delegate)的核心方法 createEditor
、setEditorData
和 setModelData
用于实现数据的 编辑功能。以下是它们的详细解释和典型用法:
1. createEditor
:创建编辑器控件
• 作用:当用户触发编辑操作(如双击单元格)时,生成一个用于编辑数据的控件(如输入框、下拉框等)。
• 调用时机:视图需要进入编辑模式时自动调用。
• 返回值:返回一个继承自 QWidget
的编辑器控件(如 QLineEdit
、QSpinBox
等)。
• 典型实现:
QWidget* MyDelegate::createEditor(
QWidget *parent,
const QStyleOptionViewItem &option,
const QModelIndex &index
) const {
// 根据数据类型创建不同编辑器
if (index.column() == 0) {
QSpinBox *editor = new QSpinBox(parent);
editor->setRange(0, 100);
return editor;
} else {
return QStyledItemDelegate::createEditor(parent, option, index);
}
}
2. setEditorData
:将模型数据加载到编辑器
• 作用:将模型中的数据(通过 Qt::EditRole
角色)填充到编辑器中,以便用户修改。
• 调用时机:createEditor
之后,编辑器显示之前。
• 典型实现:
void MyDelegate::setEditorData(
QWidget *editor,
const QModelIndex &index
) const {
// 从模型中获取原始数据
int value = index.model()->data(index, Qt::EditRole).toInt();
// 将数据设置到编辑器中
QSpinBox *spinBox = qobject_cast<QSpinBox*>(editor);
if (spinBox) {
spinBox->setValue(value);
} else {
QStyledItemDelegate::setEditorData(editor, index);
}
}
3. setModelData
:将编辑器数据保存回模型
• 作用:将用户编辑后的数据从编辑器提交回模型,并更新视图。
• 调用时机:用户完成编辑并确认(如按下回车或焦点离开编辑器)。
• 典型实现:
void MyDelegate::setModelData(
QWidget *editor,
QAbstractItemModel *model,
const QModelIndex &index
) const {
// 从编辑器获取新数据
QSpinBox *spinBox = qobject_cast<QSpinBox*>(editor);
if (spinBox) {
int value = spinBox->value();
model->setData(index, value, Qt::EditRole); // 将数据保存到模型
} else {
QStyledItemDelegate::setModelData(editor, model, index);
}
}
4. 完整代码示例
#include <QStyledItemDelegate>
#include <QSpinBox>
class SpinBoxDelegate : public QStyledItemDelegate {
public:
QWidget* createEditor(
QWidget *parent,
const QStyleOptionViewItem &option,
const QModelIndex &index
) const override {
QSpinBox *editor = new QSpinBox(parent);
editor->setFrame(false); // 无边框
editor->setRange(0, 100);
return editor;
}
void setEditorData(
QWidget *editor,
const QModelIndex &index
) const override {
int value = index.model()->data(index, Qt::EditRole).toInt();
QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
spinBox->setValue(value);
}
void setModelData(
QWidget *editor,
QAbstractItemModel *model,
const QModelIndex &index
) const override {
QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
spinBox->interpretText(); // 确保获取最新值
int value = spinBox->value();
model->setData(index, value, Qt::EditRole);
}
// 可选:调整编辑器位置和大小
void updateEditorGeometry(
QWidget *editor,
const QStyleOptionViewItem &option,
const QModelIndex &index
) const override {
editor->setGeometry(option.rect);
}
};
5. 使用场景
- 自定义编辑控件:例如在表格中使用
QDateTimeEdit
编辑日期时间。 - 数据验证:在
setModelData
中检查数据合法性。 - 动态编辑器:根据数据内容动态生成不同编辑器(如布尔值显示复选框)。
6. 关键注意事项
• 委托类型选择:
• 优先使用 QStyledItemDelegate
(支持样式表,适合现代 Qt 应用)。
• 如果不需要样式支持,可用 QItemDelegate
。
• 模型/视图通信:
• 在 setModelData
中调用 model->setData()
后,模型应触发 dataChanged
信号通知视图更新。
• 内存管理:
• Qt 会自动管理编辑器的生命周期,无需手动 delete
。
7. 流程图解
用户双击单元格 → createEditor() 创建控件 → setEditorData() 填充数据
↓
用户编辑数据 → 按回车/焦点离开 → setModelData() 提交数据 → 模型更新 → 视图刷新
通过这三个方法,可以完全控制 Qt 应用程序中数据编辑的交互逻辑。