qt5-入门-自定义委托-简单例子

本文详细介绍了Qt中的委托机制,如何通过自定义Delegate控制QTableView和QTreeView中单元格的显示样式、行为,以及如何实现数据的编辑功能,包括自定义编辑器和绘制方法。
摘要由CSDN通过智能技术生成

参考:
Qt 自定义委托_w3cschool
https://www.w3cschool.cn/learnroadqt/ov8h1j4z.html

C++ GUI Programming with Qt 4, Second Edition

本地环境:
win10专业版,64位,Qt 5.12


理论知识

Qt的model/view架构中,view只是1.对model数据的展示 2.处理用户输入。但是view只是讲用户输入委托给delegate处理

在Qt中,委托(Delegate)是一种用于控制如何显示和编辑视图中的数据的机制。它允许我们:对于不同的单元格,可以:

  • 自定义不同的外观,比如使用自定义的图标、颜色或对齐方式
  • 自定义不同的行为,比如为某些单元格提供特殊的编辑器,比如自定义的下拉列表、输入控件

委托和视图之间的区别在于:

  • 视图负责显示和编辑数据,而委托负责定义和实现如何显示和编辑特定单元格。
  • 视图是整个可见区域,如QTableViewQTreeView,而委托是针对特定单元格的。

Qt 4.4版本之后提供了两个可以被继承的 delegate 类:QItemDelegateQStyledItemDelegate。默认的 delegate 是 QStyledItemDelegate

这两个类可以被相互替代,主要区别在于,QStyledItemDelegate 使用当前的风格(style)去绘制组件。所以,在自定义 delegate 或者需要使用 Qt style sheets 时,建议使用 QStyledItemDelegate 作为父类。使用这两个类的代码通常是一样的,除了需要使用 style进行绘制的部份。如果你希望为 view item 自定义绘制函数,最好实现一个自定义的 style。这个你可以通过 QStyle 类来实现。

如果 delegate 没有支持为你的数据类型进行绘制,或者你希望自己绘制 item,那么就可以继承 QStyledItemDelegate 类,并且重写 paint() 或者还需要重写 sizeHint() 函数。paint() 函数会被每一个 item 独立调用,而 sizeHint()函数则可以定义每一个 item 的大小。在重写 paint() 函数的时候,通常需要用 if 语句找到你需要进行渲染的数据类型并进行绘制,其他的数据类型需要调用父类的实现进行绘制。

一个自定义的 delegate 也可以直接提供一个编辑器,而不是使用内置的编辑器工厂(editor item factory)。如果你需要这种功能,那么需要实现一下几个函数:

  • createEditor():返回修改数据的组件;
  • setEditorData():为 editor 提供编辑的原始数据;
  • updateEditorGeometry():保证 editor 显示在 item view 的合适位置以及大小;
  • setModelData():根据 editor 的数据更新 model 的数据。

实现效果

假设有一个table,每个单元格显示的是当前数据的平方值(原始数据是1~5)
在这里插入图片描述
双击单元格,可以编辑,编辑完成后立刻显示。
在这里插入图片描述
在这里插入图片描述

实现

model

#ifndef CUSTOMTABLEMODEL_H
#define CUSTOMTABLEMODEL_H

#include <QAbstractTableModel>

class CustomTableModel : public QAbstractTableModel
{
    Q_OBJECT
public:
    explicit CustomTableModel(QObject* parent = nullptr)
        : QAbstractTableModel(parent)
    {
        // 初始化数据
        m_data << 1 << 2 << 3 << 4 << 5;
    }

    int rowCount(const QModelIndex& parent = QModelIndex()) const override
    {
        return m_data.size();
    }

    int columnCount(const QModelIndex& parent = QModelIndex()) const override
    {
        return 1;
    }

    QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override
    {
        if (!index.isValid())
            return QVariant();

        if (role == Qt::DisplayRole) {
            return m_data.at(index.row());
        }

        return QVariant();
    }

    Qt::ItemFlags flags(const QModelIndex& index) const override
    {
        if (!index.isValid())
            return Qt::NoItemFlags;

        return Qt::ItemIsEditable | QAbstractTableModel::flags(index);
    }

    bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override
    {
        if (index.isValid() && role == Qt::EditRole) {
            m_data.replace(index.row(), value.toInt());
            emit dataChanged(index, index);
            return true;
        }

        return false;
    }

private:
    QList<int> m_data;
};

#endif // CUSTOMTABLEMODEL_H

自定义委托

#ifndef SQUAREDELEGATE_H
#define SQUAREDELEGATE_H

#include <QStyledItemDelegate>
#include <QModelIndex>
#include <QObject>
#include <QSize>
#include <QSpinBox>
#include <QPainter>



class SquareDelegate : public QStyledItemDelegate
{
public:
    QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const override
    {
        return QStyledItemDelegate::sizeHint(option, index);
    }

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

        if (index.isValid()) {
            int value = index.model()->data(index).toInt();
            QString text = QString::number(value * value);
            painter->save();
            painter->drawText(option.rect, Qt::AlignCenter, text);
            painter->restore();
        } else {
        	// 这是绘制原来的数据。如果原数据和平方值都要显示,可以把这句放在最前面
            QStyledItemDelegate::paint(painter, option, index);
        }
    }

    QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const override
    {
        QSpinBox* editor = new QSpinBox(parent);
        editor->setMinimum(0);
        editor->setMaximum(100);
        return editor;
    }

    void setEditorData(QWidget* editor, const QModelIndex& index) const override
    {
        int value = index.model()->data(index).toInt();
        QSpinBox* spinBox = static_cast<QSpinBox*>(editor);
        spinBox->setValue(value);
    }

    void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const override
    {
        /*
        QSpinBox* spinBox = static_cast<QSpinBox*>(editor);
        int value = spinBox->value();
        model->setData(index, value);
        */

        if (QSpinBox* spinBox = qobject_cast<QSpinBox*>(editor)) {
            int value = spinBox->value();
            model->setData(index, value, Qt::EditRole);
        } else {
            QStyledItemDelegate::setModelData(editor, model, index);
        }
    }

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


};


#endif // SQUAREDELEGATE_H

main

QTableView* tableView = new QTableView;
SquareDelegate* delegate = new SquareDelegate;
// 设置委托
tableView->setItemDelegate(delegate);
CustomTableModel* model = new CustomTableModel;
// 设置模型
tableView->setModel(model);
tableView->show();
  • 25
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值