自定义代理\委托 QAbstractItemDelegate

参考:QT(7)-初识委托_qt 委托-CSDN博客

一、委托 又叫 自定义代理

有的时候一个列表中的不同列 会使用到不同的 QWidget部件。比如下图(各列的数据类型不同)

               

这个时候,就是“自定义代理\委托” 的用武之地!=》类似MFC中list中的自绘功能(不同列中实现Edit、combox、checkbox、link超链接等功能)

二、QT中的委托类 抽象基类

QAbstractItemDelegate-》QItemDelegate

                                     -》QStyledItemDelegate

QStyledItemDelegate使用Qt Style Sheets来渲染单元格中的数据,这样可以更好地与应用程序的外观保持一致

三、简述功能

1、

模型:负责“组织”数据;

视图:负责“显示”数据;

委托:负责“修改”数据;

2、委托:在QT的MV模型中,处理特定类型的数据(控制数据的外观行为)!

定制 数据 的“显示”和“编辑”!

编辑日期,数值渲染颜色,字体

支持文本编辑器,下拉列表编辑器等

更新编辑器的尺寸证编辑器中的数据是否合法

3、委托:应用场景

3.1表格和列表视图:编辑单元格的数据、定制单元格外观

3.2 属性编辑器:创建自定义的属性编辑器;

3.3 文件对话框:定制文件列表的外观;

四、委托类 关键函数

4.1 virtual函数

createEditor创建用于编辑特定单元格中数据的 编辑器

setEditorData编辑器被创建后被调用,用于从数据模型获取数值,然后设置为编辑器的显示值

setModelData在编辑器编辑完成后被调用,用于将编辑器中数据更新数据模型中;

updateEditorGeometry用于设置编辑器的位置大小

一般通过继承 QStyledItemDelegate以上4个函数,便可以实现简单的自定义委托

4.2 其他函数

destroyEditor

editorEvent

helpEvent

sizeHint

这些函数并没有重要和非重要之分,需要根据不同的需求实现不同的函数,达到想要的效果。

五、使用委托 实现功能

5.1 委托 实现功能1:创建QSpinBox 编辑器、从数据模型获取值+设置编辑器显示值、将编辑器中值保存的数据模型、设置编辑器位置;

                          

delegate.h文件

#ifndef DELEGATE_H
#define DELEGATE_H

#include <QStyledItemDelegate>

//! [0]
class SpinBoxDelegate : public QStyledItemDelegate
{
    Q_OBJECT

public:
    SpinBoxDelegate(QObject *parent = nullptr);

    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;

    void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option,
                              const QModelIndex &index) const override;
};
//! [0]

#endif
delegate.cpp文件

#include "delegate.h"
#include <QSpinBox>

//! [0]
SpinBoxDelegate::SpinBoxDelegate(QObject *parent)
    : QStyledItemDelegate(parent)
{
}
//! [0]

//! [1]
QWidget *SpinBoxDelegate::createEditor(QWidget *parent,
                                       const QStyleOptionViewItem &/* option */,
                                       const QModelIndex &/* index */) const
{
    QSpinBox *editor = new QSpinBox(parent);
    editor->setFrame(false);
    editor->setMinimum(0);
    editor->setMaximum(100);

    return editor;
}
//! [1]

//! [2]
void SpinBoxDelegate::setEditorData(QWidget *editor,
                                    const QModelIndex &index) const
{
    int value = index.model()->data(index, Qt::EditRole).toInt();

    QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
    spinBox->setValue(value);
}
//! [2]

//! [3]
void SpinBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
                                   const QModelIndex &index) const
{
    QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
    spinBox->interpretText();
    int value = spinBox->value();

    model->setData(index, value, Qt::EditRole);
}
//! [3]

//! [4]
void SpinBoxDelegate::updateEditorGeometry(QWidget *editor,
                                           const QStyleOptionViewItem &option,
                                           const QModelIndex &/* index */) const
{
    editor->setGeometry(option.rect);
}
//! [4]

调用委托:tableView.setItemDelegate(&delegate);

 //将该视图的委托设置为delegate:委托delegate将完全控制项目的编辑和显示

main文件

#include "delegate.h"
#include <QApplication>
#include <QHeaderView>
#include <QStandardItemModel>
#include <QTableView>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QStandardItemModel model(4, 2);
    QTableView tableView;
    tableView.setModel(&model);

    SpinBoxDelegate delegate;
    //将该视图的委托设置为delegate:委托delegate将完全控制控制项目的编辑和显示
    tableView.setItemDelegate(&delegate);//调用委托

    tableView.horizontalHeader()->setStretchLastSection(true);

    for (int row = 0; row < 4; ++row) {
        for (int column = 0; column < 2; ++column) {
            QModelIndex index = model.index(row, column, QModelIndex());
            model.setData(index, QVariant((row + 1) * (column + 1)));
        }
    }

    tableView.setWindowTitle(QObject::tr("Spin Box Delegate"));
    tableView.show();
    return app.exec();
}

createEditor函数中:定义了一个 QSpinBox类型的编辑器,并对其进行了简单的初始化和设置;

setEditorData函数中:将模型中index位置的数据拿了出来并保存在了value中,并将value设置到了编辑器中;

setModelData函数中:将编辑器中的数据取出来设置到模型中;

updateEditorGeometry中:对位置进行了设置,editor->setGeometry(option.rect);(不执行这个生成的控件在坐标原点 )

5.2 委托 实现功能2:创建QDateEdit 编辑器、从数据模型获取值+设置编辑器显示值、将编辑器中值保存的数据模型、设置编辑器位置;

                               

delegate.cpp文件

#include "delegate.h"
#include <QSpinBox>
#include <QDateEdit>


QDateEdit::QDateEdit(QObject *parent)
    : QStyledItemDelegate(parent)
{
}

QWidget *QDateEdit::createEditor(QWidget *parent,
                                       const QStyleOptionViewItem &/* option */,
                                       const QModelIndex &/* index */) const
{
//    QSpinBox *editor = new QSpinBox(parent);
//    editor->setFrame(false);
//    editor->setMinimum(0);
//    editor->setMaximum(100);

    auto *editor = new QDateEdit(parent);
    editor->setDisplayFormat("yyyy-MM-dd");

    return editor;
}

void QDateEdit::setEditorData(QWidget *editor,
                                    const QModelIndex &index) const
{
//    int value = index.model()->data(index, Qt::EditRole).toInt();
//    QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
//    spinBox->setValue(value);

    auto value = index.model()->data(index, Qt::EditRole).toDate();
    QDateEdit *dateEdit = static_cast<QDateEdit*>(editor);
    dateEdit->setDate(value);
}

void QDateEdit::setModelData(QWidget *editor, QAbstractItemModel *model,
                                   const QModelIndex &index) const
{
//    QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
//    spinBox->interpretText();
//    int value = spinBox->value();
//    model->setData(index, value, Qt::EditRole);

    auto dateEdit = static_cast<QDateEdit*>(editor);
    auto value = dateEdit->date();
    model->setData(index,value,Qt::EditRole);
}

void QDateEdit::updateEditorGeometry(QWidget *editor,
                                           const QStyleOptionViewItem &option,
                                           const QModelIndex &/* index */) const
{
    editor->setGeometry(option.rect);
}

六、

按照这个思路,那么只要改一下里面的编辑器,就能实现不同的委托。想要实现不同的委托,只要继承QStyledItemDelegate类,并实现相应的函数,就可以实现不同的委托。

密码委托,下拉框委托(QComboBox),颜色选择委托,图标委托等等,甚至包括一些,你自己定义的控件的委托。

七、如何使用\调用委托?

场景1、委托 完全控制项目

void setItemDelegate(QAbstractItemDelegate *delegate);

    SpinBoxDelegate delegate;

    tableView.setItemDelegate(&delegate);

把该视图和模型的委托 设置为delegate;这样设置后,可以完全控制项目的编辑和显示!

场景2、委托只作用于 某列\行

void setItemDelegateForColumn(int column, QAbstractItemDelegate *delegate);
void
setItemDelegateForRow(int row, QAbstractItemDelegate *delegate);

把该视图和模型所在列\行的委托 设置为delegate,设置后,\上的项目 都将由delegate进行绘制和管理!

对这个表格控件直接使用进度条委托,也是没问题的,只需添加一行代码:ui->tableWidget->setItemDelegateForColumn(2, new ProgressDelegate(this));

  • 24
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值