Qt模型视图框架:自定义委托

这里实现一个委托使用 QSpinBox 来提供编辑功能,主要用于显示整数的模型。

从 QStyledItemDelegate 子类化委托而不是 QAbstractItemDelegate,因为QStyledItemDelegate 已经实现了 paint() 函数。 

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

提供编辑器

当视图需要提供一个编辑器时,它会要求委托提供一个适合被修改项目的编辑器小部件。 createEditor() 函数就是用来提供这个小部件的:

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

不需要保留指向编辑器小部件的指针,因为视图负责在不再需要时销毁它。

可以根据视图提供的模型索引创建不同的编辑器。例如,如果有一列整数和一列字符串,则可以根据正在编辑的列返回 QSpinBox 或 QLineEdit。

委托需要提供一个函数来将模型数据复制到编辑器中,setEditorData()就是这个函数。在这个例子中,读取显示角色中存储的数据,并相应地设置了微调框中的值。

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

向模型提交数据

当用户完成编辑时,视图要求委托通过调用 setModelData() 函数将编辑后的值存储在模型中。

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

当视图完成编辑时,委托类通过发出 closeEditor() 信号通知视图。该视图确保编辑器小部件已关闭并销毁。

更新编辑器的几何图形

管理编辑器的几何图形是委托的责任。必须在创建编辑器时以及更改视图中项目的大小或位置时设置几何图形。幸运的是,视图在视图选项对象中提供了所有必要的几何信息。

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

汇总

#ifndef SPINBOXDELEGATE_H
#define SPINBOXDELEGATE_H

#include <QStyledItemDelegate>

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

#endif // SPINBOXDELEGATE_H
#include "spinboxdelegate.h"
#include <QSpinBox>
SpinBoxDelegate::SpinBoxDelegate(QObject *parent)
    : QStyledItemDelegate(parent)
{

}

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

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

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

void SpinBoxDelegate::updateEditorGeometry(QWidget *editor,
                                           const QStyleOptionViewItem &option,
                                           const QModelIndex &/* index */) const
{
    editor->setGeometry(option.rect);
}
    QStandardItemModel * model = new QStandardItemModel;
    model->setColumnCount(2);
    model->setRowCount(2);
    model->setData(model->index(0,0),1);
    model->setData(model->index(0,1),2);
    model->setData(model->index(1,0),3);
    model->setData(model->index(1,1),4);
    QTableView view2;
    view2.setModel(model);
    view2.setItemDelegate(new SpinBoxDelegate);
    view2.show();

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值