赞
踩
委托是Qt中的一种机制,用于在Qt模型/视图架构中处理特定类型的数据。委托提供了一种方便的方法来定制特定类型的数据的显示和编辑。
委托可以做以下事情:
委托的常见应用场景包括:
model view delegate(MVD):
由于模型负责组织数据,而视图负责显示数据,所以当用户想修改显示的数据时,就要通过视图中的委托来完成
总之,委托可以用来定制Qt中各种视图组件中特定类型的数据的显示和编辑,使得开发人员能够更好地控制数据的外观和行为。使用委托可以使代码更具可重用性和灵活性。
QAbstractItemDelegate是Qt中一个抽象基类,它提供了委托类的基本功能。它是Qt中所有委托类的基类。
QItemDelegate是QAbstractItemDelegate的子类,它提供了一种通用的委托类,可以用于编辑和渲染大多数类型的数据。它提供了默认的编辑器,如QLineEdit和QSpinBox,用于编辑数值和字符串类型的数据。
QStyledItemDelegate是QItemDelegate的子类,它使用Qt Style Sheets来渲染单元格中的数据,这样可以更好地与应用程序的外观保持一致。它还提供了一些额外的功能,如支持自定义编辑器和支持编辑器工厂,这样可以更好地管理编辑器。
virtual QWidget * createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
它用于创建用于编辑特定单元格中数据的编辑器。
该函数需要三个参数:
该函数返回一个指向创建的编辑器的指针。
virtual void setEditorData(QWidget *editor, const QModelIndex &index) const
它用于将数据模型中的数据设置到编辑器中。这个函数在编辑器被创建后被调用,用于初始化编辑器的值。
它接受两个参数:
virtual void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
它用于将编辑器中的数据保存到数据模型中。这个函数在编辑器编辑完成后被调用,用于更新数据模型中的数据。
它接受三个参数:
virtual void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
它用于更新编辑器的位置和大小。这个函数在编辑器被创建后被调用,用于设置编辑器的位置和大小。
它接受三个参数:
一般通过继承 QStyledItemDelegate以上4个函数,便可以实现简单的自定义委托。
virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const = 0
它用于在视图中渲染单元格中的数据。这个函数被调用来绘制一个单元格中的数据,并且它是一个纯虚函数,需要在子类中重写。
它接受三个参数:
virtual void destroyEditor(QWidget *editor, const QModelIndex &index) const
它用于在编辑器关闭时销毁编辑器。这个函数在编辑器关闭时被调用,用于释放编辑器占用的资源。
它接受两个参数:
virtual bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
它用于处理来自编辑器的事件。这个函数在编辑器上发生事件时被调用,用于处理编辑器上的事件。
它接受四个参数:
virtual bool helpEvent(QHelpEvent *event, QAbstractItemView *view, const QStyleOptionViewItem &option, const QModelIndex &index)
virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const = 0
总之,这些函数并没有重要和非重要之分,需要根据不同的需求实现不同的函数,达到想要的效果。
官方例子在\Qt5.x.x\Examples\Qt-5.12.9\widgets\itemviews\spinboxdelegate
实现自定义数值输入
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]
main
#include "delegate.h"
#include <QApplication>
#include <QHeaderView>
#include <QStandardItemModel>
#include <QTableView>
//! [0]
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QStandardItemModel model(4, 2);
QTableView tableView;
tableView.setModel(&model);
SpinBoxDelegate delegate;
tableView.setItemDelegate(&delegate);
//! [0]
tableView.horizontalHeader()->setStretchLastSection(true);
//! [1]
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)));
}
//! [1] //! [2]
}
//! [2]
//! [3]
tableView.setWindowTitle(QObject::tr("Spin Box Delegate"));
tableView.show();
return app.exec();
}
在createEditor函数中,定义了一个 QSpinBox类型的编辑器,并对其进行了简单的初始化和设置
在setEditorData函数中,将模型中index位置的数据拿了出来并保存在了value中,并将value设置到了编辑器中
在setModelData函数中,将编辑器中的数据取出来设置到了模型中
在updateEditorGeometry中,对位置进行了设置,editor->setGeometry(option.rect);(不执行这个生成的控件在坐标原点 )
那么我们照葫芦画瓢,修改一下上面函数里的内容,看看能不能实现其他的委托:
delegate.cpp
#include "delegate.h"
#include <QSpinBox>
#include <QDateEdit>
//! [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);
auto *editor = new QDateEdit(parent);
editor->setDisplayFormat("yyyy-MM-dd");
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);
auto value = index.model()->data(index, Qt::EditRole).toDate();
QDateEdit *dateEdit = static_cast<QDateEdit*>(editor);
dateEdit->setDate(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);
auto dateEdit = static_cast<QDateEdit*>(editor);
auto value = dateEdit->date();
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]
我创建了一个QDateEdit类型的编辑器,并按照之前的思路,进行了函数的重新实现。运行效果如下:
看到这里,相信你已经对委托有了初步的认识。
通过上面的列子,你或许发现了如果按照这个思路,那么只要改一下里面的编辑器,就能实现不同的委托。确实如此,虽然上面的例子很简单,但是给我们提供了思路,想要实现不同的委托,只要继承QStyledItemDelegate类,并实现相应的函数,就可以实现不同的委托。
假设一个项目需要,密码委托,下拉框委托(QComboBox),颜色选择委托,图标委托等等,甚至包括一些,你自己定义的控件的委托。那么我们每实现一个委托,就要单独继承一次QStyledItemDelegate类吗?当然这也可以,但是不觉得总有些怪怪的吗?
有没有这样一种可能,我们创建一个类,并继承QStyledItemDelegate,然后将常用的委托全部实现,然后创建一些接口,通过这些接口对编辑器进行选择和初始化。肯定是可以的,那就期待一些吧!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。