自定义代理\委托 QAbstractItemDelegate

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

一、委托 又叫 自定义代理

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

               自定义代理\委托 QAbstractItemDelegate_第1张图片

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

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

QAbstractItemDelegate-》QItemDelegate

                                     -》QStyledItemDelegate

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

自定义代理\委托 QAbstractItemDelegate_第2张图片

三、简述功能

1、

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

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

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

自定义代理\委托 QAbstractItemDelegate_第3张图片

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 编辑器、从数据模型获取值+设置编辑器显示值、将编辑器中值保存的数据模型、设置编辑器位置;

                          自定义代理\委托 QAbstractItemDelegate_第4张图片

delegate.h文件

#ifndef DELEGATE_H
#define DELEGATE_H

#include 

//! [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 

//! [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(editor);
    spinBox->setValue(value);
}
//! [2]

//! [3]
void SpinBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
                                   const QModelIndex &index) const
{
    QSpinBox *spinBox = static_cast(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]

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

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

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

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

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

                               自定义代理\委托 QAbstractItemDelegate_第5张图片

delegate.cpp文件

#include "delegate.h"
#include 
#include 


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(editor);
//    spinBox->setValue(value);

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

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

    auto dateEdit = static_cast(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),颜色选择委托,图标委托等等,甚至包括一些,你自己定义的控件的委托。
 

你可能感兴趣的:(QT,qt)