文章目录
1、自定义代理的介绍
在Qt的MVC(Model-View-Controller)架构中,代理(Delegate)扮演着很重要的角色。代理用于控制Model在View中的显示方式,并负责处理用户与View的交互事件。在一些特殊的情况下,Qt提供了一些内置代理(例如QStyledItemDelegate、QItemDelegate等)用于控制View的显示方式。但是有时候,我们需要更加灵活地控制View的显示方式,这时就需要自定义代理。
自定义代理需要继承QAbstractItemDelegate类或则QItemDelegate类,并实现其中的一些虚函数,例如:
//返回项的大小,用于设置View中项的大小
QSize sizeHint(const QStyleOptionViewItem &option,
const QModelIndex &index) const override;
//在View中绘制项,可以通过调用painter对象的方法绘制出所需的效果
void paint(QPainter *painter,
const QStyleOptionViewItem &option,
const QModelIndex &index) const override;
//创建编辑器,用于在View中对项进行编辑
QWidget *createEditor(QWidget *parent,
const QStyleOptionViewItem &option,
const QModelIndex &index) const override;
//将Model中的数据设置到编辑器中,以便进行编辑
void setEditorData(QWidget *editor, const QModelIndex &index) const override;
//将编辑器中的数据保存到Model中
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override;
//更新编辑器的位置和大小
void updateEditorGeometry(QWidget *editor,
const QStyleOptionViewItem &option,
const QModelIndex &index) const override;
除此之外,还可以重写其他的虚函数以实现更加自定义化的效果。
自定义代理的使用方法如下:
- 创建自定义代理对象。
- 将代理对象设置到View中的项上,可以使用View的setItemDelegate()函数。
- 在Model中存储数据,并通知View进行更新。
通过自定义代理,我们可以灵活地控制View中项的显示方式,并实现一些特殊的交互效果。
2、自定义代理的案例
当我们想重新实现一个代理时,可以让子类继承QItemDelegate。实现item编辑时特定的效果,比如在item编辑时我们设置一个QSpinBox返回。
SpinBoxDelegate.h如下:
#pragma once
#include <QItemDelegate>
#include<QSpinBox>
#pragma execution_character_set("utf-8")
class SpinBoxDelegate : public QItemDelegate
{
Q_OBJECT
public:
SpinBoxDelegate(QObject *parent);
protected:
virtual QWidget* createEditor(QWidget* parent,const QStyleOptionViewItem& option,const QModelIndex& index) const override;
virtual void setEditorData(QWidget* editor, const QModelIndex& index) const override;
virtual void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const override;
virtual void updateEditorGeometry(QWidget* editor,const QStyleOptionViewItem& option,const QModelIndex& index) const override;
~SpinBoxDelegate();
};
SpinBoxDelegate.cpp如下:
#include "SpinBoxDelegate.h"
SpinBoxDelegate::SpinBoxDelegate(QObject *parent)
: QItemDelegate(parent)
{}
QWidget* SpinBoxDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
auto* spinbox = new QSpinBox(parent);
spinbox->setMinimum(0);
spinbox->setMaximum(100);
return spinbox;
}
void SpinBoxDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const
{
int value = index.model()->data(index, Qt::EditRole).toInt();
auto* spinBox = static_cast<QSpinBox*>(editor);
spinBox->setValue(value);
}
void SpinBoxDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const
{
auto* spinBox = static_cast<QSpinBox*>(editor);
//更新spinBox中的值,方便显示
spinBox->interpretText();
int value = spinBox->value();
model->setData(index, value, Qt::EditRole);
}
void SpinBoxDelegate::updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
editor->setGeometry(option.rect);
}
SpinBoxDelegate::~SpinBoxDelegate()
{}
在MainWindow中创建一个表格视图(QTableView),然后使用QStandardItemModel这个模型,通过for循环向模型中传入数据,然后在视图中设置该模型,最后创建上面的代理,通过setItemDelegage()这个接口,设置代理。
测试代码的效果如下: