Qt代理的实现(常规控件篇,含源码+注释)

一、QSpinBox控件示例图

下图为QSpinBox代理控件的实现,源码在本文第五节(源码含详细注释)
在这里插入图片描述

二、常规控件解释(个人理解)

这类控件主要有如下操作:

  1. 创建对应的对象指针并返回
  2. 获取包含代理的item值,并将其设置到控件上
  3. 获取控件的值,并将其设置到相应的item上
  4. 设置控件的显示位置

这种类型的控件代表主要有输入框、日期/时间框、进度条、轮选框等

三、需要实现的类及其内容

//1.创建相应的控件指针并返回。(每次双击包含代理的item就会调用一次此函数)
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
//参数作用
// parent:指定控件的父控件
// option:在创建控件中可以获取其rect来设置控件的绘制区域(如果这样设置,updateEditorGeometry函数可以不用,本人实测有效)。
// index:在创建控件时同样可以直接使用该参数的data将值设置到创建的控件中(如果这样设置,setEditorData函数可以不用,本人实测有效)。

//2.从传入的index获取值,设置相应控件的值。(当相应控件创建后会调用一次函数;在退出代理控件的时候也会调用该函数。)
void setEditorData(QWidget *editor, const QModelIndex &index) const
//参数作用
// editer: 获取自己创建的控件指针(需要强转,可以使用dynamic_cast<*>()转换)
// index:使用该参数的data将值设置到强转的控件中

//3.通过控件指针获取值,设置相应的item的值。(当退出代理控件的时候会调用该函数。)
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
//参数作用
// editor:获取控件中的值(该值用于设置到item中)
// model:通过index获取当前item从而设置值
// index:配合model获取当前item

//4.设置控件的显示位置(在创建后会调用一次)
//如果该函数没有任何内容,绘制的控件将会绘制在QTableView对象的左上角(当需求方是QTableView时,在创建控件时的option也可以获取rect来设置绘画区域)
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
//参数作用
// editor:获取自己创建的控件指针(需要强转,可以使用dynamic_cast<*>()转换)
// option:获取rect从而设置其绘制的位置

四、使用方法

使用时像按钮代理那样直接使用相应View对象的setModel函数将代理设置到相应位置即可,双击相应item会自动显示出来

五、QSpinBox控件源码(定义、调用)

CSpinBoxDelegate类

CSpinBoxDelegate.h

#ifndef CSPINBOXDELEGATE_H
#define CSPINBOXDELEGATE_H

#include <QObject>
#include <QItemDelegate>
#include <QStyledItemDelegate>
class CSpinBoxDelegate : public QStyledItemDelegate
{
    Q_OBJECT
public:
    explicit CSpinBoxDelegate(QStyledItemDelegate *parent = nullptr);
    QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
    void setEditorData(QWidget *editor, const QModelIndex &index) const;
    void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const;
    void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const;
};
#endif // CSPINBOXDELEGATE_H

CSpinBoxDelegate.cpp

#include "CSpinBoxDelegate.h"
#include <QSpinBox>

CSpinBoxDelegate::CSpinBoxDelegate(QStyledItemDelegate *parent) : QStyledItemDelegate(parent)
{

}

QWidget *CSpinBoxDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    //一定要指定父类,否则创建的控件将会显示独立窗口
    QSpinBox *spinBox = new QSpinBox(parent);
    return spinBox;
}

void CSpinBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
    //拿到创建的QSpinBox控件
    QSpinBox *spinBox = dynamic_cast<QSpinBox *>(editor);
    //获取当前item的值
    int value = index.data().toInt();
    spinBox->setValue(value);
}

void CSpinBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
    //拿到创建的QSpinBox控件
    QSpinBox *spinBox = dynamic_cast<QSpinBox *>(editor);
    //通过传入的model和index变量将值设置到当前item上
    model->setData(index, spinBox->value());
}

void CSpinBoxDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    //拿到创建的QSpinBox控件
    QSpinBox *spinBox = dynamic_cast<QSpinBox *>(editor);
    //设置控件的显示位置
    spinBox->setGeometry(option.rect);
}

CMainWindow调用类

CMainWindow.h

#ifndef CMAINWINDOW_H
#define CMAINWINDOW_H

#include <QMainWindow>
#include <QStandardItemModel>
#include <CSpinBoxDelegate.h>
namespace Ui {
class CMainWindow;
}

class CMainWindow : public QMainWindow
{
    Q_OBJECT
public:
    explicit CMainWindow(QWidget *parent = 0);
    ~CMainWindow();
private:
    Ui::CMainWindow *ui;
    QStandardItemModel  *m_model;   //tableView的模板变量
    CSpinBoxDelegate    *m_delegate;    //tableView的代理变量
};
#endif // CMAINWINDOW_H

CMainWindow.cpp

#include "CMainWindow.h"
#include "ui_CMainWindow.h"

CMainWindow::CMainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::CMainWindow)
{
    ui->setupUi(this);
    //创建view模型对象
    m_model = new QStandardItemModel;
    //添加标题
    m_model->setHorizontalHeaderLabels(QStringList() << "第一列" << "第二列" << "第三列");
    //设置view模型对象
    ui->tableView->setModel(m_model);
    //创建代理对象
    m_delegate = new CSpinBoxDelegate;
    //设置代理列
    ui->tableView->setItemDelegateForColumn(2, m_delegate);
    //给tableview添加值
    for(int index = 0; index != 5; ++index)
    {
        m_model->setItem(index, 0, new QStandardItem(QString("第%1列第1列").arg(index)));
        m_model->setItem(index, 1, new QStandardItem(QString("第%1列第2列").arg(index)));
        m_model->setItem(index, 2, new QStandardItem(QString("%1").arg(index)));
    }
}

CMainWindow::~CMainWindow()
{
    delete m_delegate;
    delete m_model;
    delete ui;
}

总结

常规控件主要适合双击显示的代理(不需要保持显示在界面上的控件),如单选按钮、复选按钮等如此实现出来会感觉缺点东西,并且设置的控件获取和设置值也需符合代理设定,

相关文章

Qt代理的实现(按钮篇,含源码+注释)
Qt之QTableView的简单使用(含源码+注释)
Qt之QTableView设置多列表头复选框(自定义QHeaderView)、单元格复选框(含源码+注释)
Qt之QSortFilterProxyModel的简单使用(QTableView搜索功能,含源码+注释)
Qt之QTreeView的简单使用(含源码+注释)
Qt之QListView的简单使用(含源码+注释)

友情提示——哪里看不懂可私哦,让我们一起互相进步吧
(创作不易,请留下一个免费的赞叭 谢谢 ^o^/)

注:文章为作者编程过程中所遇到的问题和总结,内容仅供参考,若有错误欢迎指出。
注:如有侵权,请联系作者删除

  • 13
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 14
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

lw向北.

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

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

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

打赏作者

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

抵扣说明:

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

余额充值