QStyledItemDelegate的函数的介绍

前言

Qt版本:6.8.0

公共函数

1. 构造函数与析构函数

QStyledItemDelegate(QObject *parent = nullptr)
  • 作用:创建样式化的项委托实例。
  • 参数
    • parent: 父对象,用于内存管理(默认为 nullptr)。
  • 示例
    QTableView tableView;
    QStyledItemDelegate *delegate = new QStyledItemDelegate(&tableView);
    tableView.setItemDelegate(delegate);
    
virtual ~QStyledItemDelegate()
  • 作用:析构函数,清理资源。通常无需手动调用,由父对象自动管理。

2. 显示与数据转换

QString displayText(const QVariant &value, const QLocale &locale) const
  • 作用:将数据 value 转换为显示的文本,考虑本地化 (locale)。
  • 参数
    • value: 模型中的数据(如整数、日期等)。
    • locale: 本地化设置(如日期格式、数字分隔符)。
  • 返回值:格式化后的文本(QString)。
  • 示例(重写以自定义显示):
    QString MyDelegate::displayText(const QVariant &value, const QLocale &locale) const {
        if (value.type() == QVariant::Date) {
            return locale.toString(value.toDate(), "yyyy-MM-dd");
        }
        return QStyledItemDelegate::displayText(value, locale);
    }
    

3. 编辑器工厂管理

QItemEditorFactory *itemEditorFactory() const
  • 作用:获取当前使用的编辑器工厂。
  • 返回值:指向 QItemEditorFactory 的指针。
void setItemEditorFactory(QItemEditorFactory *factory)
  • 作用:设置自定义的编辑器工厂,用于创建特定数据类型的编辑器。
  • 参数
    • factory: 新的编辑器工厂。
  • 示例
    QItemEditorFactory *factory = new QItemEditorFactory;
    delegate->setItemEditorFactory(factory);
    

4. 核心重写函数

QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
  • 作用:创建用于编辑 index 数据的编辑器(如 QLineEditQSpinBox)。
  • 参数
    • parent: 编辑器的父控件。
    • option: 样式信息(如字体、颜色)。
    • index: 模型索引。
  • 返回值:创建的编辑器控件指针。
  • 示例(为整数类型创建 QSpinBox):
    QWidget* MyDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const {
        if (index.data().type() == QVariant::Int) {
            QSpinBox *editor = new QSpinBox(parent);
            editor->setRange(0, 100);
            return editor;
        }
        return QStyledItemDelegate::createEditor(parent, option, index);
    }
    
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
  • 作用:绘制项的内容,使用当前样式确保外观一致。
  • 参数
    • painter: 绘图工具。
    • option: 样式选项。
    • index: 模型索引。
  • 示例(高亮特定项):
    void MyDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const {
        QStyleOptionViewItem opt = option;
        initStyleOption(&opt, index); // 初始化默认样式
        if (index.data().toInt() > 50) {
            opt.palette.setColor(QPalette::Text, Qt::red);
        }
        QStyledItemDelegate::paint(painter, opt, index);
    }
    
void setEditorData(QWidget *editor, const QModelIndex &index) const
  • 作用:将模型数据加载到编辑器。
  • 参数
    • editor: 创建的编辑器。
    • index: 模型索引。
  • 示例(设置 QSpinBox 的值):
    void MyDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const {
        int value = index.data().toInt();
        QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
        spinBox->setValue(value);
    }
    
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
  • 作用:将编辑器数据保存回模型。
  • 参数
    • editor: 编辑器控件。
    • model: 目标模型。
    • index: 模型索引。
  • 示例(保存 QSpinBox 的值):
    void MyDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const {
        QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
        spinBox->interpretText(); // 确保获取最新值
        model->setData(index, spinBox->value());
    }
    
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
  • 作用:返回项的建议大小。
  • 返回值QSize 对象。
  • 示例(根据内容调整大小):
    QSize MyDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const {
        QSize size = QStyledItemDelegate::sizeHint(option, index);
        QString text = index.data().toString();
        if (text.length() > 10) {
            size.rwidth() += 50; // 增加宽度
        }
        return size;
    }
    
`void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
  • 作用:调整编辑器的位置和大小,使其覆盖项。
  • 参数
    • editor: 编辑器控件。
    • option: 样式选项。
    • index: 模型索引。
  • 示例
    void MyDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const {
        editor->setGeometry(option.rect); // 使编辑器覆盖项区域
    }
    

virtual void destroyEditor(QWidget *editor, const QModelIndex &index) const

  • 作用销毁编辑器对象,当编辑完成或取消时调用。用于清理资源或断开信号槽连接。
  • 参数
    • editor: 要销毁的编辑器控件指针。
    • index: 关联的模型索引(通常用于判断是否需要特殊清理)。
  • 返回值:无。
  • 示例(自定义清理逻辑):
    class MyDelegate : public QStyledItemDelegate {
    public:
        void destroyEditor(QWidget *editor, const QModelIndex &index) const override {
            // 自定义清理逻辑(如断开信号槽)
            if (auto customEditor = qobject_cast<MyCustomEditor*>(editor)) {
                disconnect(customEditor, &MyCustomEditor::someSignal, nullptr, nullptr);
            }
            // 调用基类实现完成默认清理
            QStyledItemDelegate::destroyEditor(editor, index);
        }
    };
    

virtual bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)

  • 作用处理视图项上的事件(如鼠标点击、键盘事件)。返回 true 表示事件已处理。
  • 参数
    • event: 事件对象(如 QMouseEventQKeyEvent)。
    • model: 关联的数据模型。
    • option: 视图项的样式信息(如位置、字体)。
    • index: 事件触发的模型索引。
  • 返回值booltrue 表示事件被处理,阻止进一步传递。
  • 示例(双击触发编辑或自定义操作):
    bool MyDelegate::editorEvent(QEvent *event, QAbstractItemModel *model,
                                const QStyleOptionViewItem &option,
                                const QModelIndex &index) {
        if (event->type() == QEvent::MouseButtonDblClick) {
            // 触发编辑
            return true;
        } else if (event->type() == QEvent::MouseButtonPress) {
            QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
            if (mouseEvent->button() == Qt::RightButton) {
                // 显示自定义右键菜单
                showContextMenu(option.rect.topLeft(), index);
                return true;
            }
        }
        // 其他事件交由基类处理
        return QStyledItemDelegate::editorEvent(event, model, option, index);
    }
    

virtual bool helpEvent(QHelpEvent *event, QAbstractItemView *view, const QStyleOptionViewItem &option, const QModelIndex &index)

  • 作用处理帮助事件(如工具提示 QEvent::ToolTip 或状态栏提示)。返回 true 表示事件已处理。
  • 参数
    • event: 帮助事件对象(QHelpEvent 子类,如 QToolTipEvent)。
    • view: 触发事件的视图控件(如 QTableView)。
    • option: 视图项的样式信息。
    • index: 关联的模型索引。
  • 返回值booltrue 表示事件被处理。
  • 示例(自定义工具提示内容):
    bool MyDelegate::helpEvent(QHelpEvent *event, QAbstractItemView *view,
                              const QStyleOptionViewItem &option,
                              const QModelIndex &index) {
        if (event->type() == QEvent::ToolTip) {
            // 获取数据
            QString data = index.data(Qt::DisplayRole).toString();
            // 自定义工具提示
            QToolTip::showText(event->globalPos(), 
                              QString("详细信息: %1").arg(data), 
                              view, option.rect);
            return true;
        }
        return QStyledItemDelegate::helpEvent(event, view, option, index);
    }
    

总结

  1. destroyEditor

    • 用于清理自定义编辑器的资源。
    • 必须调用基类实现以确保默认清理逻辑。
    • 当编辑器需要释放非 Qt 管理的资源(如外部句柄)时重写
  2. editorEvent

    • 处理交互事件(如点击、双击、右键菜单)。
    • 常用于实现自定义交互逻辑(如按钮、复选框)。
    • 在表格项中嵌入交互控件(如按钮、开关)。
  3. helpEvent

    • 处理工具提示或其他帮助信息。
    • 可动态生成提示内容(如显示额外数据)。
    • 为复杂数据项提供动态提示(如预览图片、长文本)。

5. 保护函数

void initStyleOption(QStyleOptionViewItem *option, const QModelIndex &index) const
  • 作用:初始化 option 的默认样式(如文本对齐、字体)。
  • 示例(在自定义 paint 中调用):
    void MyDelegate::paint(...) {
        QStyleOptionViewItem opt;
        initStyleOption(&opt, index); // 先获取默认样式
        // 修改 opt 后继续绘制
    }
    
bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
  • 作用:处理视图项上的事件(如鼠标点击)。
  • 返回值true 表示事件已处理。
  • 示例(双击启动编辑器):
    bool MyDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) {
        if (event->type() == QEvent::MouseButtonDblClick) {
            // 触发编辑
            return true;
        }
        return QStyledItemDelegate::editorEvent(event, model, option, index);
    }
    
bool eventFilter(QObject *editor, QEvent *event)
  • 作用:过滤编辑器的事件(如回车键确认)。
  • 示例(回车键提交数据):
    bool MyDelegate::eventFilter(QObject *editor, QEvent *event) {
        if (event->type() == QEvent::KeyPress) {
            QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
            if (keyEvent->key() == Qt::Key_Enter) {
                emit commitData(editor); // 提交数据
                return true;
            }
        }
        return QStyledItemDelegate::eventFilter(editor, event);
    }
    

信号

1. void closeEditor(QWidget *editor, QAbstractItemDelegate::EndEditHint hint = NoHint)

触发时机:

  • 当用户完成对某个单元格的编辑(如按下Enter、Tab、Esc,或点击其他地方导致编辑结束)时,委托(delegate)会关闭编辑器控件,此时会发出该信号。 例如:你在QTableView 的某个单元格输入内容后,按下 Enter 键,编辑器关闭,这时会触发 closeEditor 信号。

参数解释:

  • QWidget *editor:指向当前正在编辑的编辑器控件(如 QLineEdit、QComboBox 等)。
  • QAbstractItemDelegate::EndEditHint hint:指示编辑结束的原因或方式。常用的枚举值有:
    • NoHint:无特殊提示。
    • EditNextItem:请求编辑下一个项目。
    • EditPreviousItem:请求编辑上一个项目。
    • SubmitModelCache:提交模型缓存。
    • RevertModelCache:撤销模型缓存。

示例:

connect(delegate, &QAbstractItemDelegate::closeEditor, this, [](QWidget *editor, QAbstractItemDelegate::EndEditHint hint){
    qDebug() << "Editor closed:" << editor << "Hint:" << hint;
});

2. void commitData(QWidget *editor)

触发时机:

  • 当编辑器中的数据需要提交到模型时,会发出该信号。

    通常在用户完成编辑(如按下 Enter、切换到其他单元格、编辑器失去焦点等)时触发。

    例如:你在 QLineEdit 编辑单元格内容,按下 Enter 或切换到其他单元格,编辑器会将数据提交到模型,并发出commitData 信号。

参数解释:

  • QWidget *editor:指向当前正在编辑的编辑器控件。这个信号通常在编辑器中的数据需要提交到模型时发出。

示例:

connect(delegate, &QAbstractItemDelegate::commitData, this, [](QWidget *editor){
    qDebug() << "Commit data from editor:" << editor;
});

3. void sizeHintChanged(const QModelIndex &index)

触发时机:

  • 当某个项的推荐显示尺寸(sizeHint)发生变化时,委托会发出该信号,通知视图重新布局。

    例如:你自定义的委托在某些条件下改变了单元格的高度或宽度(如内容变多、字体变大),需要通知视图更新显示时,会触发该信号。

参数解释:

  • const QModelIndex &index:指向模型中发生尺寸变化的项的索引。这个信号在某个项的 sizeHint(推荐显示尺寸)发生变化时发出,通常用于通知视图重新布局。

示例:

connect(delegate, &QAbstractItemDelegate::sizeHintChanged, this, [](const QModelIndex &index){
    qDebug() << "Size hint changed for index:" << index;
});

示例

在这里插入图片描述


示例 1:整数输入委托(使用 QSpinBox

功能:为整数类型的数据提供带有范围限制的 QSpinBox 编辑器。
class IntSpinBoxDelegate : public QStyledItemDelegate {
public:
    IntSpinBoxDelegate(int min, int max, QObject *parent = nullptr)
        : QStyledItemDelegate(parent), m_min(min), m_max(max) {}

    // 创建 QSpinBox 编辑器
    QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option,
                          const QModelIndex &index) const override {
        QSpinBox *editor = new QSpinBox(parent);
        editor->setRange(m_min, m_max);
        editor->setFrame(false); // 无边框
        return editor;
    }

    // 将模型数据加载到编辑器
    void setEditorData(QWidget *editor, const QModelIndex &index) const override {
        int value = index.data(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(); // 确保获取最新值
        model->setData(index, spinBox->value(), Qt::EditRole);
    }

private:
    int m_min, m_max;
};

// 使用方式
QTableView tableView;
tableView.setItemDelegate(new IntSpinBoxDelegate(0, 100, &tableView));

示例 2:日期选择委托(使用 QDateEdit

功能:为日期类型的数据提供日历下拉编辑器。
class DateEditDelegate : public QStyledItemDelegate {
public:
    DateEditDelegate(QObject *parent = nullptr) : QStyledItemDelegate(parent) {}

    QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option,
                          const QModelIndex &index) const override {
        QDateEdit *editor = new QDateEdit(parent);
        editor->setCalendarPopup(true); // 启用日历弹窗
        editor->setDisplayFormat("yyyy-MM-dd");
        return editor;
    }

    void setEditorData(QWidget *editor, const QModelIndex &index) const override {
        QDate date = index.data(Qt::EditRole).toDate();
        QDateEdit *dateEdit = static_cast<QDateEdit*>(editor);
        dateEdit->setDate(date);
    }

    void setModelData(QWidget *editor, QAbstractItemModel *model,
                     const QModelIndex &index) const override {
        QDateEdit *dateEdit = static_cast<QDateEdit*>(editor);
        model->setData(index, dateEdit->date(), Qt::EditRole);
    }

    // 格式化显示文本
    QString displayText(const QVariant &value, const QLocale &locale) const override {
        return value.toDate().toString("yyyy-MM-dd");
    }
};

// 使用方式
tableView.setItemDelegateForColumn(1, new DateEditDelegate(&tableView));

示例 3:富文本(HTML)渲染委托

功能:显示带有 HTML 格式的文本(如加粗、颜色)。
class RichTextDelegate : public QStyledItemDelegate {
public:
    using QStyledItemDelegate::QStyledItemDelegate;

    // 自定义绘制
    void paint(QPainter *painter, const QStyleOptionViewItem &option,
               const QModelIndex &index) const override {
        QStyleOptionViewItem opt = option;
        initStyleOption(&opt, index);

        // 使用 QTextDocument 渲染 HTML
        QTextDocument doc;
        doc.setHtml(opt.text);
        doc.setDefaultFont(opt.font);

        painter->save();
        painter->translate(opt.rect.topLeft());
        doc.drawContents(painter);
        painter->restore();
    }

    // 调整项大小以适应 HTML 内容
    QSize sizeHint(const QStyleOptionViewItem &option,
                   const QModelIndex &index) const override {
        QTextDocument doc;
        doc.setHtml(index.data().toString());
        doc.setDefaultFont(option.font);
        return QSize(doc.idealWidth(), doc.size().height());
    }
};

// 使用方式
tableView.setItemDelegate(new RichTextDelegate(&tableView));

示例 4:按钮委托(点击触发动作)

功能:在项中绘制按钮,点击后执行自定义操作。
class ButtonDelegate : public QStyledItemDelegate {
    Q_OBJECT
public:
    using QStyledItemDelegate::QStyledItemDelegate;

    // 绘制按钮
    void paint(QPainter *painter, const QStyleOptionViewItem &option,
               const QModelIndex &index) const override {
        QStyleOptionButton button;
        button.rect = option.rect.adjusted(2, 2, -2, -2);
        button.text = "Action";
        button.state = QStyle::State_Enabled;

        QApplication::style()->drawControl(QStyle::CE_PushButton, &button, painter);
    }

    // 处理点击事件
    bool editorEvent(QEvent *event, QAbstractItemModel *model,
                    const QStyleOptionViewItem &option,
                    const QModelIndex &index) override {
        if (event->type() == QEvent::MouseButtonRelease) {
            QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
            if (option.rect.contains(mouseEvent->pos())) {
                emit buttonClicked(index);
                return true;
            }
        }
        return false;
    }

signals:
    void buttonClicked(const QModelIndex &index);
};

// 使用方式(连接信号)
ButtonDelegate *delegate = new ButtonDelegate(&tableView);
tableView.setItemDelegateForRow(0, delegate);
connect(delegate, &ButtonDelegate::buttonClicked, [](const QModelIndex &index) {
    qDebug() << "Button clicked at row:" << index.row();
});

示例 5:进度条委托(使用 QStyle 绘制)

功能:将数值显示为进度条样式。
class ProgressBarDelegate : public QStyledItemDelegate {
public:
    using QStyledItemDelegate::QStyledItemDelegate;

    void paint(QPainter *painter, const QStyleOptionViewItem &option,
               const QModelIndex &index) const override {
        // 获取数据值(假设范围 0-100)
        int value = index.data().toInt();
        value = qBound(0, value, 100);

        // 绘制进度条
        QStyleOptionProgressBar progressBarOption;
        progressBarOption.rect = option.rect.adjusted(2, 2, -2, -2);
        progressBarOption.minimum = 0;
        progressBarOption.maximum = 100;
        progressBarOption.progress = value;
        progressBarOption.text = QString("%1%").arg(value);
        progressBarOption.textVisible = true;

        QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption, painter);
    }
};

// 使用方式
tableView.setItemDelegateForColumn(2, new ProgressBarDelegate(&tableView));

示例 6:自定义图标+文本委托

功能:在项左侧显示图标,右侧显示文本。
class IconTextDelegate : public QStyledItemDelegate {
public:
    IconTextDelegate(const QIcon &icon, QObject *parent = nullptr)
        : QStyledItemDelegate(parent), m_icon(icon) {}

    void paint(QPainter *painter, const QStyleOptionViewItem &option,
               const QModelIndex &index) const override {
        QStyleOptionViewItem opt = option;
        initStyleOption(&opt, index);

        // 绘制图标
        QRect iconRect = opt.rect;
        iconRect.setWidth(16); // 图标宽度
        m_icon.paint(painter, iconRect, Qt::AlignLeft | Qt::AlignVCenter);

        // 绘制文本(向右偏移图标宽度)
        QRect textRect = opt.rect.adjusted(20, 0, 0, 0);
        painter->drawText(textRect, opt.displayAlignment, opt.text);
    }

private:
    QIcon m_icon;
};

// 使用方式
tableView.setItemDelegate(new IconTextDelegate(QIcon(":/icon.png"), &tableView));

总结

  • 核心方法:通过重写 paintcreateEditorsetEditorDatasetModelData 实现不同效果。
  • 交互处理:使用 editorEvent 捕获点击或键盘事件。
  • 性能优化:复杂绘制(如 HTML)需注意性能,避免频繁创建 QTextDocument
  • 信号传递:通过自定义信号(如 buttonClicked)将委托事件传递到业务逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值