[Qt基础内容-09] Qt中MVC的C(Delegate)

[Qt基础内容-09] Qt中MVC的C(Delegate),第1张

[Qt基础内容-09] Qt中MVC的C(Delegate)

Qt有自己的MVC框架,分别是model(模型)、view(视图)、delegate(委托),这篇文章,简单的介绍以下Qt中有关delegate(委托)的类以及一些基本的使用。
Qt官方的文档已经很详细了,如果想要详细的去了解,不如花点精力去看官方文档。

文章目录
  • [Qt基础内容-09] Qt中MVC的C(Delegate)
    • 类继承的结构
    • QStyledItemDelegate、QItemDelegate
      • paint + sizeHint
      • createEditor、setEditorData、setModelData

Delegate,英文翻译为委托,主要和数据在View上的显示和编辑有关。

类继承的结构

Qt中的委托类,都继承自QAbstractItemDelegate。

和之前介绍的model一样,同样,我们也只介绍能够直接使用的类;
根据官方文档中的说明

QItemDelegate and QStyledItemDelegate. However, the default delegate is QStyledItemDelegate. These two classes are independent alternatives to painting and providing editors for items in views. The difference between them is that QStyledItemDelegate uses the current style to paint its items. We therefore recommend using QStyledItemDelegate as the base class when implementing custom delegates or when working with Qt style sheets. The code required for either class should be equal unless the custom delegate needs to use the style for drawing

QItemDelegate QStyledItemDelegate。然而,默认的委托是QStyledItemDelegate。这两个类是对视图中的项进行绘制和提供编辑器的独立选择。它们之间的区别是QStyledItemDelegate使用当前样式来绘制它的项。因此,我们建议在实现自定义委托或使用Qt样式表时使用QStyledItemDelegate作为基类。两个类所需的代码应该相等,除非自定义委托需要使用绘图样式

Qt官方建议是继承QStyledItemDelegate来实现自定义委托,QStyledItemDelegate和QItemDelegate的主要区别在于,QStyledItemDelegate使用当前样式来绘制,并且QItemDelegate已经被弃用了,建议使用QStyledItemDelegate。有一个讨论帖,请看What is the difference between QStyledItem and QItemDelegate?

QStyledItemDelegate、QItemDelegate

由于本人对于其机制了解的还不够透彻,所以只介绍,在项目中,常用到的一些接口,以及怎么使用。
根据我的理解,主要是有个大块,一个是显示,另外一个是编辑。

paint + sizeHint

这个部分是显示,在paint函数中,可以绘制你想要绘制的东西。比如说一些图标一些简单的控件(像QProgressBar)

  1. paint

    函数原型:

    void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
    

    这个函数,可以用于在指定的index处,绘制你想要的控件。
    根据Qt官方中的例子:

     void WidgetDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
                                const QModelIndex &index) const
     {
         if (index.column() == 1) {
             int progress = index.data().toInt();
    
             QStyleOptionProgressBar progressBarOption;
             progressBarOption.rect = option.rect;
             progressBarOption.minimum = 0;
             progressBarOption.maximum = 100;
             progressBarOption.progress = progress;
             progressBarOption.text = QString::number(progress) + "%";
             progressBarOption.textVisible = true;
    
             QApplication::style()->drawControl(QStyle::CE_ProgressBar,
                                                &progressBarOption, painter);
         } else
             QStyledItemDelegate::paint(painter, option, index);
     }
    

  2. sizeHint

    函数原型为:

    QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
    

    函数作用为,为

    Sets the data to be displayed and edited by the editor from the data model item specified by the model index.

    考虑到option提供的样式信息,返回委托显示index指定的项所需的大小

    注意的一点是,当你为QTableView设置代理时,你需要调用resizeColumnsToContents、resizeColumnToContents、resizeRowsToContents、resizeRowToContents来触发这个函数,否则不会触发。
    使用的例子如下:

    QSize MyDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
    {
        if (index.column() == 0) {
            return QSize(20, 20);
        }
    
        return QStyledItemDelegate::sizeHint(option, index);
    }
    
createEditor、setEditorData、setModelData

这一部分是编辑,可以设置双击编辑时的编辑方式,比如一个QSpinBox或者QComboBox等
三个函数的原型为:

    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;
  1. createEditor

    创建编辑器,也就是编辑时的编辑方式。

  2. setEditorData

    设置编辑器的数据。

  3. setModelData

    根据编辑器修改之后设置model的值。

基本的用法如下:

QWidget *MyDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    if (index.column() == 2) {
        // 为第二列创建一个QSpinBox编辑器
        QSpinBox* spinBox = new QSpinBox(parent);
        spinBox->rect() = option.rect;
        return spinBox;
    }

    return QStyledItemDelegate::createEditor(parent, option, index);
}

void MyDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
    if (index.column() == 2) {
        // 将model中的数据,赋值给editor
        auto spinBox = static_cast<QSpinBox*>(editor);
        spinBox->setValue(index.data().toInt());
    } else {
        return QStyledItemDelegate::setEditorData(editor, index);
    }
}

void MyDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
    if (index.column() == 2) {
        // 把编辑器里的数据,重新给到model中
        auto spinBox = static_cast<QSpinBox*>(editor);
        model->setData(index, spinBox->value(), Qt::EditRole);
    } else {
        return QStyledItemDelegate::setModelData(editor, model, index);
    }
}

实现的效果如下:

但是这个编辑框,需要双击才会显示出来。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/2990610.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-09-23
下一篇 2022-09-23

发表评论

登录后才能评论

评论列表(0条)

保存