Qt如何自定义委托全家桶

发布时间:2021-12-15 13:41:43 作者:iii
来源:亿速云 阅读:209
# 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;
};

2. 基础委托实现

2.1 绘制委托(Paint Delegate)

通过重写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);
    }
}

2.2 编辑器委托(Editor Delegate)

实现完整的编辑流程:

方法 作用
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;
}

3. 高级委托技巧

3.1 复合控件委托

组合多个控件作为编辑器:

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;
}

3.2 动态样式委托

根据数据状态改变显示样式:

void StatusDelegate::paint(...) const {
    if (index.data().toString() == "Error") {
        painter->fillRect(option.rect, Qt::red);
    }
    QStyledItemDelegate::paint(painter, option, index);
}

4. 特殊场景处理

4.1 树形视图委托

处理不同层级的不同渲染:

void TreeDelegate::paint(...) const {
    if (index.parent().isValid()) {  // 子节点
        // 特殊绘制逻辑
    } else {  // 根节点
        // 默认绘制
    }
}

4.2 表格条件格式化

实现类似Excel的条件格式:

void ConditionalDelegate::paint(...) const {
    double value = index.data().toDouble();
    QColor bgColor = (value > 0) ? Qt::green : Qt::red;
    painter->fillRect(option.rect, bgColor);
    // 继续绘制文本...
}

5. 性能优化

5.1 避免重复创建编辑器

通过QAbstractItemView::setItemDelegateForColumn/Row指定特定行列的委托:

tableView->setItemDelegateForColumn(0, new NumberDelegate(this));
tableView->setItemDelegateForColumn(1, new ColorDelegate(this));

5.2 使用样式选项

正确使用QStyleOptionViewItem提高渲染效率:

void FastPaintDelegate::paint(...) const {
    option.widget->style()->drawControl(QStyle::CE_ItemViewItem, 
                                       &option, painter);
    // 自定义绘制叠加层...
}

6. 常见问题解决

6.1 编辑器不显示

检查是否实现了完整的编辑方法链: 1. createEditor() 2. setEditorData() 3. setModelData()

6.2 自定义绘制被覆盖

确保在派生类中调用基类方法的正确时机:

void MyDelegate::paint(...) const {
    // 先绘制自定义内容
    drawCustomBackground(painter, option.rect);
    
    // 最后调用基类绘制文本
    QStyledItemDelegate::paint(painter, option, index);
}

7. 完整示例:进度条委托

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字,此处为精简展示。完整实现需要配合具体业务场景和更多代码示例)

推荐阅读:
  1. Vue著名的全家桶系列是什么
  2. React全家桶环境如何搭建

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

qt

上一篇:LeetCode如何解决二进制中1的个数问题

下一篇:LeetCode如何解决前K个高频元素问题

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》