【Qt】一文总结Qt表格项目的代理类

一、开篇

软件设计中,表格是一种常用的数据呈现控件,然而在实际的项目中,会出现对表格中的单行数据操作的情况:例如可能会编辑表格、删除表格数据等。这两个操作方式在设计中,可能会同时放在数据表格的行当中。例如如下图所示的效果:

在上图中,左侧是一列选择框、最右侧的每一个表格单元中都放置了两个按钮,表示对该行数据的操作。

本文,将描述在Qt中,如何使用Qt提供的表格代理类来实现这种功能。
效果走一波:

(注)本文只描述左侧选择框代理类的实现。

首先来看看Qt提供的代码类。在开发中,常使用QItemDelegateQStyledItemDelegate代理类。

(1)QItemDelegate:该类为表格模型中的数据项提供显示和编辑工具。

(2)QStyledItemDelegate:该类与QItemDelegate代理类功能大同小异,但是QStyledItemDelegate接管了绘制Qt项视图的工作。所有我们在创建新代理时建议使用QStyledItemDelegate。

带自定义我们的代理类使,需要重载createEditor()paint()两个虚函数:

(1)createEditor
函数原型如下:

QWidget *QStyledItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) cons

该函数将返回用于编辑由索引指定的条目的小部件。parent部件和option样式选项用于控制编辑器部件的显示方式。

(2)paint
函数原型如下:

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

该函数使用index指定的item项的给定painter和option样式选项呈现代理类。


二、一个示例

本文以选择框代理类为例。
为了实现我们自己的选择框代理类,我们需要将QStyledItemDelegate作为父类,并重载paint()editorEvent(),在该类中可以放置自己类的私有数据:

class checkBoxDelegate : public QStyledItemDelegate
{
    Q_OBJECT
public:
    checkBoxDelegate(int checkBoxWidth,int checkBoxHeight,QObject *parent = nullptr)
    :QStyledItemDelegate(parent),
    m_checkBoxWidth(checkBoxWidth),
    m_checkBoxHeight(checkBoxHeight)
    {}
    ~checkBoxDelegate()override{}

    void paint(QPainter* painter, const QStyleOptionViewItem & option,
               const QModelIndex &index) const override;
    bool editorEvent(QEvent *event, QAbstractItemModel *m_model,
                     const QStyleOptionViewItem &option,const QModelIndex &index) override;

    int m_checkBoxWidth,m_checkBoxHeight;
};

然后实现painteditorEvent两个函数,如下代码:

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

    QStyleOptionViewItem viewOption(option);
    initStyleOption(&viewOption, index);
    if (option.state.testFlag(QStyle::State_HasFocus))
        viewOption.state = viewOption.state ^ QStyle::State_HasFocus;

    painter->setRenderHint(QPainter::Antialiasing,true);
    QStyledItemDelegate::paint(painter, viewOption, index);

    bool data = index.model()->data(index, Qt::UserRole).toBool();


    int nHalf = (option.rect.width() - m_checkBoxWidth)/2;
    int nTop = (option.rect.height() - m_checkBoxHeight)/2;

    QStyleOptionButton checkBoxOptionStyle;
    checkBoxOptionStyle.state = data ? QStyle::State_On : QStyle::State_Off;
    checkBoxOptionStyle.state |= QStyle::State_Enabled;
    checkBoxOptionStyle.iconSize = QSize(12, 12);
    checkBoxOptionStyle.rect =  QRect(option.rect.left() + nHalf ,
                                option.rect.top() + nTop,  m_checkBoxWidth, m_checkBoxHeight);

    QCheckBox checkBox;

    QApplication::style()->drawControl(QStyle::CE_CheckBox, &checkBoxOptionStyle, painter, &checkBox);
}


bool checkBoxDelegate::editorEvent(QEvent *event, QAbstractItemModel *m_model,
                                       const QStyleOptionViewItem &option,const QModelIndex &index)
{
    QRect decorationRect = option.rect;

    QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
    if (event->type() == QEvent::MouseButtonPress && decorationRect.contains(mouseEvent->pos()))
    {
        bool data = m_model->data(index, Qt::UserRole).toBool();
        m_model->setData(index,!data, Qt::UserRole);
    }

    return true;
}

对于代理类中还有更多可以重载的虚函数:
在这里插入图片描述
在开发中,可以根据实际情况来重新重载和实现,具体功能可参见官方文档(https://doc.qt.io/qt-5/qstyleditemdelegate.html#paint

三、代理类的使用

当我们设计到代理类后,可以在表格中使用了。使用setItemDelegateForColumn()为表格设置代理:

m_tableView->setItemDelegateForColumn(0,new checkBoxDelegate(20,20,this));

本文完!


搜索/关注【嵌入式小生】微信公众号。回复2077即可获取本文源码工程。

  • 3
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

iriczhao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值