Delegate(委托)机制是 Qt 模型/视图架构中的核心组成部分,它充当了数据模型和视图显示之间的"中介者",主要负责数据的可视化呈现和编辑交互。通过使用 Delegate,可以自定义项目的外观和编辑行为,而不必修改底层的数据模型。

Delegate介绍

委托的作用

  1. 渲染项目-可视化呈现:Delegate 负责绘制视图中的每一个项目。这可以通过重写 paint() 函数来实现,以及处理不同显示状态(正常、选中、悬停、禁用等)。
  2. 提供编辑器:当用户尝试编辑一个项目时,Delegate 创建一个合适的编辑器控件。这个过程包括三个步骤:
    • 使用 createEditor() 创建编辑器。
    • 使用 setEditorData() 将当前数据从模型加载到编辑器中。
    • 使用 setModelData() 将编辑器中的更改保存回模型。
  3. 布局管理调整大小提示:Delegate 可以通过 sizeHint() 提供每个项目的理想尺寸,从而影响布局。
    • 提供项目尺寸提示(sizeHint

    • 处理内容对齐和边距

标准 Delegate 类

Qt 提供了两个主要的 Delegate 类:

  • QItemDelegate:这是默认的委托类,提供了经典外观的编辑器控件,适用于需要精细控制绘制细节的情况。
  • QStyledItemDelegate:推荐用于新应用程序,因为它使用当前平台的主题绘制元素,确保了视觉的一致性。

 Delegate 工作流程

要使用 Delegate,通常需要以下步骤:

  1. 子类化:根据需求创建一个继承自 QStyledItemDelegateQItemDelegate 的新类,并根据需要重写上述方法。
  2. 设置 Delegate:将你的 Delegate 实例设置给视图,例如 QListView, QTableView, 或 QTreeView,通过调用这些视图的 setItemDelegate() 方法。

标准工作序列:

  1. 视图请求绘制 → paint()

  2. 用户开始编辑 → createEditor()

  3. 数据加载到编辑器 → setEditorData()

  4. 编辑完成提交 → setModelData()

  5. 编辑器销毁 → destroyEditor()

时序图示例:

[View] -> [Delegate] : paint()
[View] -> [Delegate] : createEditor()
[Delegate] -> [Editor] : setEditorData()
[User edits] -> [Editor] : 修改数据
[Editor] -> [Delegate] : commitData()
[Delegate] -> [Model] : setModelData()

    自定义 Delegate 

    假设想要为 QTableView 中的日期列添加一个日期选择器作为编辑器:创建一个继承自 QStyledItemDelegate 的类,并重写 createEditor(), setEditorData(), 和 setModelData() 方法来处理日期的选择与显示。

    关键技术

    1. 绘制优化技术

    void paint(QPainter *painter, ...) override {
        // 1. 样式预处理
        QStyleOptionViewItem opt = option;
        initStyleOption(&opt, index);
        
        // 2. 背景绘制优化
        if (opt.state & QStyle::State_Selected) {
            painter->fillRect(opt.rect, opt.palette.highlight());
        }
        
        // 3. 内容绘制分级
        QString text = index.data().toString();
        QTextOption textOption;
        textOption.setAlignment(Qt::AlignVCenter);
        painter->drawText(opt.rect.adjusted(2,0,-2,0), text, textOption);
    }

    2. 编辑器生命周期管理

    // 创建时缓存引用
    QWidget *createEditor(...) override {
        QWidget *editor = new CustomEditor(parent);
        m_activeEditors.insert(index, editor);  // 维护编辑器映射
        return editor;
    }
    
    // 销毁时资源清理
    void destroyEditor(...) override {
        m_activeEditors.remove(index);
        editor->deleteLater();
    }

    高级应用

    1. 复合内容委托

    void paint(QPainter *painter, ...) override {
        // 绘制图标
        QIcon icon = qvariant_cast<QIcon>(index.data(IconRole));
        QRect iconRect = option.rect.adjusted(2,2,-2,-2);
        iconRect.setWidth(16);
        icon.paint(painter, iconRect);
        
        // 绘制主文本
        QString mainText = index.data(Qt::DisplayRole).toString();
        QRect textRect = option.rect.adjusted(20,0,0,0);
        painter->drawText(textRect, mainText);
        
        // 绘制辅助文本
        QString subText = index.data(SubTextRole).toString();
        QRect subRect = textRect.adjusted(0,15,0,0);
        QFont subFont = painter->font();
        subFont.setPointSize(7);
        painter->setFont(subFont);
        painter->drawText(subRect, subText);
    }

    2. 动态样式委托

    void initStyleOption(QStyleOptionViewItem *option, ...) override {
        QStyledItemDelegate::initStyleOption(option, index);
        
        // 根据数据值动态修改样式
        if (index.data(Qt::UserRole+1).toBool()) {
            option->font.setBold(true);
            option->backgroundBrush = QColor("#FFF8E1");
        }
        
        // 添加自定义样式属性
        option->styleObject->setProperty("dataStatus", 
            index.data(StatusRole).toString());
    }

    性能关键点

    1. 绘制性能优化

      • 避免在paint()中创建临时对象

      • 使用QStyle::drawControl()代替直接绘制

      • 对复杂项目启用QPaintDevice::devicePixelRatioF()支持

    2. 内存管理策略

      // 使用对象池管理编辑器
      QHash<QModelIndex, QWeakPointer<QWidget>> m_editorPool;
      
      QWidget *createEditor(...) override {
          if (m_editorPool.contains(index) && !m_editorPool[index].isNull()) {
              return m_editorPool[index].data();
          }
          QWidget *editor = new CustomEditor(parent);
          m_editorPool[index] = editor;
          return editor;
      }
    1. 模型交互优化

      • 批量操作时使用beginResetModel()/endResetModel()

      • 对大数据集实现fetchMore()延迟加载

    典型问题

    1. 编辑冲突处理

    bool editorEvent(QEvent *event, QAbstractItemModel *model,
                    const QStyleOptionViewItem &option,
                    const QModelIndex &index) override
    {
        if (event->type() == QEvent::MouseButtonDblClick) {
            if (m_activeEditors.contains(index)) {
                return true;  // 阻止重复编辑
            }
        }
        return QStyledItemDelegate::editorEvent(event, model, option, index);
    }

    2. 自定义验证提示

    void setModelData(QWidget *editor, QAbstractItemModel *model,
                     const QModelIndex &index) const override
    {
        QLineEdit *lineEdit = qobject_cast<QLineEdit*>(editor);
        if (lineEdit->hasAcceptableInput()) {
            QStyledItemDelegate::setModelData(editor, model, index);
        } else {
            QToolTip::showText(editor->mapToGlobal(QPoint(0,0)),
                              tr("输入格式无效"));
        }
    }

    调试技巧

    1. 绘制调试标记

    void paint(QPainter *painter, ...) override {
        painter->save();
        painter->setPen(Qt::red);
        painter->drawRect(option.rect.adjusted(0,0,-1,-1));  // 绘制项目边界
        painter->restore();
        // ...正常绘制逻辑
    }
    1. 事件日志记录

    bool eventFilter(QObject *object, QEvent *event) override {
        qDebug() << "Delegate event:" << event->type() 
                 << "target:" << object;
        return QStyledItemDelegate::eventFilter(object, event);
    }

        Delegate 机制的强大之处在于其灵活性,开发者可以通过继承和定制实现各种复杂的界面效果,同时保持与模型/视图架构的无缝集成。理解其工作原理对于开发高性能、可维护的 Qt 界面至关重要。

    QItemDelegate 

    QItemDelegate 是 Qt 模型/视图框架中的一个类,用于处理模型中数据项的显示和编辑功能。它是 Qt 提供的两个标准委托类之一(另一个是 QStyledItemDelegate)。

    主要特性

    1. 渲染功能:控制视图中的项目如何绘制

    2. 编辑功能:为修改项目数据提供编辑器

    3. 尺寸提示:提供项目的尺寸信息

    基本用法

    QItemDelegate *delegate = new QItemDelegate(parent);
    view->setItemDelegate(delegate);

     

    常用方法

    • paint() - 渲染项目

    • sizeHint() - 返回显示项目所需的大小

    • createEditor() - 返回用于编辑项目的控件

    • setEditorData() - 设置要在编辑器中显示和编辑的数据

    • setModelData() - 从编辑器控件获取数据并存储到模型中

    使用场景

    虽然 QStyledItemDelegate 现在是推荐的默认委托,但在以下情况下 QItemDelegate 可能仍然有用:

    • 需要与旧版 Qt 保持兼容性

    • 需要实现不依赖样式表的非常自定义的绘制

    示例:自定义委托

    class MyDelegate : public QItemDelegate {
    public:
        void paint(QPainter *painter, const QStyleOptionViewItem &option,
                   const QModelIndex &index) const override {
            // 自定义绘制实现
        }
        
        QSize sizeHint(const QStyleOptionViewItem &option,
                       const QModelIndex &index) const override {
            // 自定义尺寸提示
        }
    };

    实际应用建议

    1. 简单场景:对于大多数现代Qt应用,优先考虑使用QStyledItemDelegate

    2. 自定义绘制:当需要完全控制项目绘制时,可以继承QItemDelegate

    3. 性能考虑:QItemDelegate在某些简单场景下可能有轻微性能优势

    QStyledItemDelegate 

    QStyledItemDelegate 是 Qt 框架中用于模型/视图架构的高级委托类,自 Qt 4.4 引入后成为官方推荐的标准委托实现。

    主要功能

    1. 样式化绘制QStyledItemDelegate 通过应用当前平台的主题和样式来绘制视图中的项目,确保了界面元素的一致性。
    2. 编辑支持:类似于 QItemDelegate,它也支持为视图中的项目提供定制的编辑器控件,并且可以控制如何将数据从模型传递给编辑器以及如何将编辑结果返回到模型。
    3. 灵活的委托行为:通过重写 paint()sizeHint() 等关键函数,可以实现高度定制化的显示逻辑。

    常见用途

    • 当你需要确保你的自定义绘制逻辑遵循用户系统的样式指南时,QStyledItemDelegate 提供了一个更好的起点。
    • 对于那些需要根据系统主题动态调整外观的应用程序来说,QStyledItemDelegate 可以自动适应这些变化,而不需要额外的编码工作。

    核心特性

    1. 样式表支持

      • 完整支持 Qt Style Sheets (QSS)

      • 可实现对单元格样式的高度定制

      QTableView::item {
          color: blue;
          background-color: yellow;
      }
    1. 现代样式集成

      • 自动适应不同平台样式(Windows/MacOS/Linux)

      • 正确渲染高DPI显示

    2. 数据类型智能处理

      • 自动识别常见数据类型(int, double, QString等)

      • 为不同类型提供合适的默认编辑器

    两者对比

    特性 QStyledItemDelegate QItemDelegate
    样式支持 完整QSS支持 基本样式支持
    绘制方式 使用样式绘制 直接绘制
    编辑器创建 自动类型匹配 需要手动实现
    平台外观一致性 更好 一般
    推荐使用场景 Qt 4.4+新项目 旧项目维护

    核心方法

    1. 绘制方法

    void paint(QPainter *painter, 
              const QStyleOptionViewItem &option,
              const QModelIndex &index) const override
    {
        // 基本绘制流程
        QStyleOptionViewItem opt = option;
        initStyleOption(&opt, index);  // 关键初始化
        
        // 特殊处理选中状态
        if (opt.state & QStyle::State_Selected)
            painter->fillRect(opt.rect, QColor("#D6E6FF"));
        
        // 调用基类绘制
        QStyledItemDelegate::paint(painter, opt, index);
    }

    2. 编辑器创建流程

    QWidget *createEditor(QWidget *parent,
                          const QStyleOptionViewItem &option,
                          const QModelIndex &index) const override
    {
        // 根据数据类型返回不同编辑器
        if (index.data().type() == QVariant::Int)
            return new QSpinBox(parent);
        else if (index.data().type() == QVariant::Date)
            return new QDateEdit(parent);
        
        return QStyledItemDelegate::createEditor(parent, option, index);
    }

    高级应用技巧

    1. 自定义数据渲染

    void paint(QPainter *painter, ...) override
    {
        // 绘制进度条
        if (index.column() == 2) {
            int progress = index.data().toInt();
            QStyleOptionProgressBar progressBarOption;
            progressBarOption.rect = option.rect.adjusted(2, 2, -2, -2);
            progressBarOption.progress = progress;
            progressBarOption.text = QString::number(progress) + "%";
            progressBarOption.textVisible = true;
            
            QApplication::style()->drawControl(
                QStyle::CE_ProgressBar, 
                &progressBarOption, 
                painter);
        } else {
            QStyledItemDelegate::paint(painter, option, index);
        }
    }

    2. 数据验证

    QWidget *createEditor(...) override
    {
        QLineEdit *editor = qobject_cast<QLineEdit*>(
            QStyledItemDelegate::createEditor(parent, option, index));
        
        if (editor && index.column() == 0) {
            // 设置输入验证器
            QRegularExpressionValidator *validator = 
                new QRegularExpressionValidator(QRegularExpression("[A-Za-z0-9_]+"), editor);
            editor->setValidator(validator);
        }
        return editor;
    }

    自定义 Qt 委托类

    下面将详细介绍各种实用的自定义委托类实现,涵盖不同应用场景,并提供完整的代码示例。

    基础样式类委托

    1. 高亮文本委托

    class HighlightDelegate : public QStyledItemDelegate {
    public:
        explicit HighlightDelegate(QObject* parent = nullptr) 
            : QStyledItemDelegate(parent) {}
    
        void paint(QPainter* painter, const QStyleOptionViewItem& option,
                  const QModelIndex& index) const override {
            QStyleOptionViewItem opt = option;
            initStyleOption(&opt, index);
    
            // 高亮匹配文本
            QString text = opt.text;
            if (!m_highlightText.isEmpty() && text.contains(m_highlightText, Qt::CaseInsensitive)) {
                QTextDocument doc;
                doc.setHtml(text.replace(m_highlightText, 
                    QString("<span style='background-color:yellow;color:black'>%1</span>")
                    .arg(m_highlightText)));
                painter->save();
                painter->translate(opt.rect.topLeft());
                doc.drawContents(painter);
                painter->restore();
            } else {
                QStyledItemDelegate::paint(painter, opt, index);
            }
        }
    
        void setHighlightText(const QString& text) { 
            m_highlightText = text; 
        }
    
    private:
        QString m_highlightText;
    };
    
    // 使用示例
    HighlightDelegate* delegate = new HighlightDelegate(view);
    delegate->setHighlightText("重要");
    view->setItemDelegate(delegate);

    2. 斑马线交替行委托

    class ZebraDelegate : public QStyledItemDelegate {
    public:
        void paint(QPainter* painter, const QStyleOptionViewItem& option,
                  const QModelIndex& index) const override {
            QStyleOptionViewItem opt = option;
            initStyleOption(&opt, index);
    
            // 交替行背景色
            if (index.row() % 2 == 0) {
                opt.backgroundBrush = QColor(240, 240, 240);
            }
    
            QStyledItemDelegate::paint(painter, opt, index);
        }
    };

    数据可视化类委托

    1. 进度条委托

    class ProgressBarDelegate : public QStyledItemDelegate {
    public:
        void paint(QPainter* painter, const QStyleOptionViewItem& option,
                  const QModelIndex& index) const override {
            // 获取进度值(0-100)
            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;
            progressBarOption.state = option.state;
            
            QApplication::style()->drawControl(
                QStyle::CE_ProgressBar, &progressBarOption, painter);
        }
    };

    2. 星级评分委托

    class StarRatingDelegate : public QStyledItemDelegate {
    public:
        void paint(QPainter* painter, const QStyleOptionViewItem& option,
                  const QModelIndex& index) const override {
            int stars = index.data().toInt();
            QRect rect = option.rect.adjusted(2, 2, -2, -2);
            
            painter->save();
            painter->setRenderHint(QPainter::Antialiasing);
            
            QPen pen(QColor(255, 180, 0), outlinePen(Qt::black);
            outlinePen.setWidth(1);
            painter->setPen(outlinePen);
            
            // 绘制五角星
            for (int i = 0; i < 5; ++i) {
                if (i < stars) {
                    painter->setBrush(pen.color());
                } else {
                    painter->setBrush(Qt::white);
                }
                
                QPointF center(rect.left() + i * (rect.height() + 2) + rect.height()/2, 
                              rect.center().y());
                drawStar(painter, center, rect.height()/2);
            }
            
            painter->restore();
        }
    
    private:
        void drawStar(QPainter* painter, const QPointF& center, double radius) const {
            QPolygonF star;
            for (int i = 0; i < 5; ++i) {
                double angle = 2 * M_PI * i / 5 - M_PI / 2;
                star << center + QPointF(radius * cos(angle), radius * sin(angle));
                angle += 2 * M_PI / 10;
                star << center + QPointF(radius * 0.4 * cos(angle), radius * 0.4 * sin(angle));
            }
            painter->drawPolygon(star);
        }
    };

    交互增强类委托

    1. 按钮委托

    class ButtonDelegate : public QStyledItemDelegate {
        Q_OBJECT
    public:
        explicit ButtonDelegate(QObject* parent = nullptr)
            : QStyledItemDelegate(parent) {}
    
        void paint(QPainter* painter, const QStyleOptionViewItem& option,
                  const QModelIndex& index) const override {
            QStyleOptionButton button;
            button.rect = option.rect.adjusted(4, 4, -4, -4);
            button.text = "操作";
            button.state = option.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.adjusted(4,4,-4,-4).contains(mouseEvent->pos())) {
                    emit buttonClicked(index);
                    return true;
                }
            }
            return false;
        }
    
    signals:
        void buttonClicked(const QModelIndex& index);
    };

    2. 复选框委托

    class CheckBoxDelegate : public QStyledItemDelegate {
    public:
        explicit CheckBoxDelegate(QObject* parent = nullptr)
            : QStyledItemDelegate(parent) {}
    
        void paint(QPainter* painter, const QStyleOptionViewItem& option,
                  const QModelIndex& index) const override {
            bool checked = index.data().toBool();
            
            QStyleOptionButton checkbox;
            checkbox.rect = QRect(option.rect.x() + option.rect.width()/2 - 8,
                                 option.rect.y() + option.rect.height()/2 - 8,
                                 16, 16);
            checkbox.state = QStyle::State_Enabled | (checked ? QStyle::State_On : QStyle::State_Off);
            
            QApplication::style()->drawControl(QStyle::CE_CheckBox, &checkbox, painter);
        }
    
        bool editorEvent(QEvent* event, QAbstractItemModel* model,
                        const QStyleOptionViewItem& option,
                        const QModelIndex& index) override {
            if (event->type() == QEvent::MouseButtonRelease) {
                model->setData(index, !index.data().toBool());
                return true;
            }
            return false;
        }
    };

    复合内容类委托

    1. 图标+文本委托

    class IconTextDelegate : public QStyledItemDelegate {
    public:
        void paint(QPainter* painter, const QStyleOptionViewItem& option,
                  const QModelIndex& index) const override {
            QStyleOptionViewItem opt = option;
            initStyleOption(&opt, index);
    
            // 绘制背景
            opt.widget->style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter);
    
            // 绘制图标 (32x32)
            QRect iconRect = opt.rect.adjusted(4, 4, -4, -4);
            iconRect.setWidth(32);
            QIcon icon = index.data(Qt::DecorationRole).value<QIcon>();
            icon.paint(painter, iconRect);
    
            // 绘制主文本
            QRect textRect = opt.rect.adjusted(40, 4, -4, -4);
            QString text = index.data(Qt::DisplayRole).toString();
            painter->drawText(textRect, Qt::AlignLeft | Qt::AlignVCenter, text);
    
            // 绘制辅助文本
            if (index.data(Qt::UserRole).isValid()) {
                QFont font = painter->font();
                font.setPointSize(font.pointSize() - 1);
                painter->setFont(font);
                QString subText = index.data(Qt::UserRole).toString();
                painter->drawText(textRect.adjusted(0, 15, 0, 0), 
                                Qt::AlignLeft | Qt::AlignTop, subText);
            }
        }
    
        QSize sizeHint(const QStyleOptionViewItem& option,
                      const QModelIndex& index) const override {
            return QSize(200, 40); // 固定高度
        }
    };

    2. 多行文本委托

    class MultiLineDelegate : public QStyledItemDelegate {
    public:
        void paint(QPainter* painter, const QStyleOptionViewItem& option,
                  const QModelIndex& index) const override {
            QStyleOptionViewItem opt = option;
            initStyleOption(&opt, index);
    
            const QString text = index.data().toString();
            QTextOption textOption;
            textOption.setWrapMode(QTextOption::WordWrap);
            
            painter->save();
            painter->setPen(opt.palette.text().color());
            painter->drawText(opt.rect, text, textOption);
            painter->restore();
        }
    
        QSize sizeHint(const QStyleOptionViewItem& option,
                      const QModelIndex& index) const override {
            QTextDocument doc;
            doc.setTextWidth(option.rect.width());
            doc.setPlainText(index.data().toString());
            return QSize(option.rect.width(), doc.size().height());
        }
    };

    数据验证类委托

    1. IP地址输入委托

    class IPAddressDelegate : public QStyledItemDelegate {
    public:
        QWidget* createEditor(QWidget* parent,
                             const QStyleOptionViewItem& option,
                             const QModelIndex& index) const override {
            QLineEdit* editor = new QLineEdit(parent);
            
            // IP地址验证正则
            QString ipRange = "(?:[0-1]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])";
            QRegularExpression ipRegex("^" + ipRange + "\\." + ipRange + "\\." + 
                                     ipRange + "\\." + ipRange + "$");
            QRegularExpressionValidator* validator = 
                new QRegularExpressionValidator(ipRegex, editor);
            editor->setValidator(validator);
            
            return editor;
        }
    };

    2. 日期范围委托

    class DateRangeDelegate : public QStyledItemDelegate {
    public:
        DateRangeDelegate(QDate minDate, QDate maxDate, QObject* parent = nullptr)
            : QStyledItemDelegate(parent), m_minDate(minDate), m_maxDate(maxDate) {}
    
        QWidget* createEditor(QWidget* parent,
                             const QStyleOptionViewItem& option,
                             const QModelIndex& index) const override {
            QDateEdit* editor = new QDateEdit(parent);
            editor->setDisplayFormat("yyyy-MM-dd");
            editor->setCalendarPopup(true);
            editor->setMinimumDate(m_minDate);
            editor->setMaximumDate(m_maxDate);
            return editor;
        }
    
    private:
        QDate m_minDate;
        QDate m_maxDate;
    };

    高级应用示例

    1. 可折叠树节点委托

    class TreeExpandDelegate : public QStyledItemDelegate {
    public:
        void paint(QPainter* painter, const QStyleOptionViewItem& option,
                  const QModelIndex& index) const override {
            QStyleOptionViewItem opt = option;
            initStyleOption(&opt, index);
    
            // 绘制背景
            opt.widget->style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter);
    
            // 绘制展开/折叠标记
            if (index.model()->hasChildren(index)) {
                QStyleOptionViewItem expandOpt = opt;
                expandOpt.rect.setWidth(16);
                expandOpt.features |= QStyleOptionViewItem::HasDecoration;
                
                QTreeView* tree = qobject_cast<QTreeView*>(opt.widget);
                if (tree && tree->isExpanded(index)) {
                    expandOpt.icon = QApplication::style()->standardIcon(QStyle::SP_ArrowDown);
                } else {
                    expandOpt.icon = QApplication::style()->standardIcon(QStyle::SP_ArrowRight);
                }
                
                opt.widget->style()->drawControl(QStyle::CE_ItemViewItem, &expandOpt, painter);
            }
    
            // 绘制文本内容
            opt.rect.adjust(20, 0, 0, 0);
            QStyledItemDelegate::paint(painter, opt, index);
        }
    
        bool editorEvent(QEvent* event, QAbstractItemModel* model,
                        const QStyleOptionViewItem& option,
                        const QModelIndex& index) override {
            if (event->type() == QEvent::MouseButtonPress && 
                option.rect.adjusted(0,0,20,0).contains(static_cast<QMouseEvent*>(event)->pos())) {
                QTreeView* tree = qobject_cast<QTreeView*>(option.widget);
                if (tree) {
                    tree->setExpanded(index, !tree->isExpanded(index));
                    return true;
                }
            }
            return false;
        }
    };

    2. 颜色选择委托

    class ColorPickerDelegate : public QStyledItemDelegate {
        Q_OBJECT
    public:
        QWidget* createEditor(QWidget* parent,
                             const QStyleOptionViewItem& option,
                             const QModelIndex& index) const override {
            QColorDialog* dialog = new QColorDialog(parent);
            dialog->setModal(true);
            connect(dialog, &QColorDialog::colorSelected, [=](const QColor& color) {
                emit commitData(dialog);
                emit closeEditor(dialog);
            });
            return dialog;
        }
    
        void setEditorData(QWidget* editor,
                          const QModelIndex& index) const override {
            QColor color = index.data(Qt::BackgroundRole).value<QColor>();
            QColorDialog* dialog = qobject_cast<QColorDialog*>(editor);
            if (dialog) dialog->setCurrentColor(color);
        }
    
        void setModelData(QWidget* editor,
                         QAbstractItemModel* model,
                         const QModelIndex& index) const override {
            QColorDialog* dialog = qobject_cast<QColorDialog*>(editor);
            if (dialog) {
                model->setData(index, dialog->currentColor(), Qt::BackgroundRole);
            }
        }
    
        void paint(QPainter* painter, const QStyleOptionViewItem& option,
                  const QModelIndex& index) const override {
            QColor color = index.data(Qt::BackgroundRole).value<QColor>();
            painter->fillRect(option.rect.adjusted(1,1,-1,-1), color);
            
            QPen pen(Qt::black);
            pen.setWidth(1);
            painter->setPen(pen);
            painter->drawRect(option.rect.adjusted(1,1,-1,-1));
        }
    };

    使用建议

    1. 性能考虑

      • 对于大数据集,避免在paint()中进行复杂计算

      • 考虑使用QStyledItemDelegate::initStyleOption()保持样式一致性

    2. 内存管理

      • 确保正确销毁编辑器对象

      • 对于频繁使用的委托,考虑对象池模式

    3. 模型交互

      • 使用正确的角色(Qt::DisplayRole, Qt::EditRole等)

      • 对于自定义数据类型,注册元类型(qRegisterMetaType)

    4. 样式定制

      • 优先使用样式表进行外观定制

      • 对于复杂效果,考虑使用QGraphicsEffect

    这些示例覆盖了Qt委托开发的主要场景,可根据实际需求进行组合或扩展。

    Logo

    GitCode 天启AI是一款由 GitCode 团队打造的智能助手,基于先进的LLM(大语言模型)与多智能体 Agent 技术构建,致力于为用户提供高效、智能、多模态的创作与开发支持。它不仅支持自然语言对话,还具备处理文件、生成 PPT、撰写分析报告、开发 Web 应用等多项能力,真正做到“一句话,让 Al帮你完成复杂任务”。

    更多推荐