1 写在前面的话

我们在之前写的《QT(7)-初识委托》文章末尾提到,“使用一个类继承QStyledItemDelegate实现常用的控件委托,在使用时可以直接调用接口,灵活实现各种委托”。我们接下来几篇文章将先详细讲解各个控件的委托,最后整理成一个类,并分享源码。如果大家感兴趣,可以点个关注,后面我们一起学习!

讲解比较详细,大家可以跟着一步一步做,自己就可以实现了。

2 需要用到的部分知识

《QT(3)-QTableView》

《QT(4)-QAbstractItemView》

《QT(6)-QStandardItemModel》

《QT(7)-初识委托》

3 实现QSpinBox委托

3.1 第一步

文件结构如下:

在设计师界面拖拽一个tableview到MainWindow中,并对其进行初始化。

需要主要的是 void initTable(...);这个函数是我在经常使用QTableView时通用的设置,不仅可以在这个项目使用,也可以在其他项目中使用



代码如下:

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H #include <QMainWindow> class QStandardItemModel;
class QTableView; QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE class MainWindow : public QMainWindow
{
Q_OBJECT public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
void init();
//设置表格
void initTable(QTableView *tableView,int rowHeight = 25,bool Editable=false,bool isSorting = false,bool verticalHeadVisible=false,
bool isLastTensile = true,bool isShowGrid = true); private:
Ui::MainWindow *ui;
QStandardItemModel *model;
};
#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h" #include <QStandardItemModel> MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
this->initTable(ui->tableView,27,true);
this->init();
} MainWindow::~MainWindow()
{
delete ui;
} void MainWindow::init()
{
QStringList columnNames;
columnNames<<"QSpinBox"<<"QComboBox"<<"QCheckBox"<<"···"; model = new QStandardItemModel;
model->setRowCount(10);
model->setHorizontalHeaderLabels(columnNames);
ui->tableView->setModel(model); } void MainWindow::initTable(QTableView *tableView,int rowHeight,bool Editable,bool isSorting,bool verticalHeadVisible,bool isLastTensile,bool isShowGrid)
{
/*设置样式*/
tableView->setProperty("model",true);
/*设置默认行高*/
tableView->verticalHeader()->setDefaultSectionSize(rowHeight);
/*设置交替行颜色--允许交替行颜色*/
tableView->setAlternatingRowColors(true);
/*设置水平/垂直滚动模式--一次滚动一个项目*/
tableView->setHorizontalScrollMode(QAbstractItemView::ScrollPerItem);
tableView->setVerticalScrollMode(QAbstractItemView::ScrollPerItem);
/*设置选择行为--每次选择只有一整行*/
tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
/*设置拖放行为--不允许拖放*/
tableView->setDragDropMode(QAbstractItemView::NoDragDrop);
/*设置选择模式--只能选择一个项目*/
tableView->setSelectionMode(QAbstractItemView::SingleSelection);
/*设置Tab导航键--允许使用Tab键导航,shift+tab反向导航*/
tableView->setTabKeyNavigation(true);
/*设置是否自动换行--取消自动换行*/
tableView->setWordWrap(false);
/*设置文本省略模式--省略号不会出现在文本中*/
tableView->setTextElideMode(Qt::ElideNone);
/*设置左上角全选按钮--禁用*/
tableView->setCornerButtonEnabled(false);
/*设置是否支持表头排序--应该和表头是否可以单击保持一致*/
tableView->setSortingEnabled(isSorting);
/*设置是否显示网格线*/
tableView->setShowGrid(isShowGrid);
/*设置垂直表头是否可见*/
tableView->verticalHeader()->setVisible(verticalHeadVisible);
/*设置选中一行表头是否加粗--不加粗*/
tableView->horizontalHeader()->setHighlightSections(false);
/*设置最后一行是否拉伸填充*/
tableView->horizontalHeader()->setStretchLastSection(isLastTensile);
/*设置行标题最小宽度尺寸*/
tableView->horizontalHeader()->setMinimumSectionSize(0);
/*设置行标题最小高度*/
tableView->horizontalHeader()->setFixedHeight(rowHeight); /*设置表头是否可以单击--不可单击*/
#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0))
tableView->horizontalHeader()->setSectionsClickable(isSorting);
#else
tableView->horizontalHeader()->setClickable(false);
#endif /*是否可编辑*/
if(Editable)
{
tableView->setEditTriggers(QAbstractItemView::CurrentChanged|QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed);
}
else
{
tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
}
}

3.2 第二步

  1. 我们首先创建一个类Delegate继承QStyledItemDelegate,同时定义以下四个函数:
QWidget * createEditor(..)
void setEditorData(...)
void setModelData(...)
void updateEditorGeometry(...)

这四个函数的作用以及意义,详见:《QT(7)-初识委托》这里不在赘述。

  1. 创建一些 QSpinBox相关参数,并创建相应参数的外部设置接口
    /*QSpinBox相关参数*/
int sboxMaxValue;/*微调框的最大值*/
int sboxMinValue;/*微调框的最小值*/ QString sboxPrefixStr;/*微调框前缀*/
QString sboxSuffixStr;/*微调框后缀*/ int sboxSingleStep;/*微调框步长*/
int sboxInitValue;/*微调框初始值*/
QAbstractSpinBox::StepType sboxStepType;/*微调框步长类型*/ /*QSpinBox设置相关参数函数*/
void setSboxMaxValue(const int max);
void setSboxMinValue(const int min);
void setSboxPrefixStr(const QString &prefix);
void setSboxSuffixStr(const QString &suffix);
void setSboxSingleStep(const int SingleStep);
void setSboxInitValue(const int initValue);
void setSboxStepType(QAbstractSpinBox::StepType st);

这里我定义了很多参数,实际应用的时候有些参数并用不到,大家根据需求定义。

  1. 创建给这些参数初始化的函init()

具体头文件如下:

delegate.h:

#ifndef DELEGATE_H
#define DELEGATE_H #include <QStyledItemDelegate> class Delegate : public QStyledItemDelegate
{
Q_OBJECT
public:
Delegate(QObject *parent = nullptr);
protected:
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;
private:
void init();
public:
/*QSpinBox设置相关参数函数*/
void setSboxMaxValue(const int max);
void setSboxMinValue(const int min);
void setSboxPrefixStr(const QString &prefix);
void setSboxSuffixStr(const QString &suffix);
void setSboxSingleStep(const int SingleStep);
void setSboxInitValue(const int initValue);
void setSboxStepType(QAbstractSpinBox::StepType st);
private:
/*QSpinBox相关参数*/
int sboxMaxValue;/*微调框的最大值*/
int sboxMinValue;/*微调框的最小值*/ QString sboxPrefixStr;/*微调框前缀*/
QString sboxSuffixStr;/*微调框后缀*/ int sboxSingleStep;/*微调框步长*/
int sboxInitValue;/*微调框初始值*/ QAbstractSpinBox::StepType sboxStepType;/*微调框步长类型*/ };
#endif // DELEGATE_H

3.3 第三步

下面我们逐个实现这四个虚函数函数:

  1. 创建编辑器
QWidget *Delegate::createEditor(QWidget *parent, const QStyleOptionViewItem &/*option*/, const QModelIndex &index) const
{
QSpinBox *sbox = new QSpinBox(parent);
sbox->setRange(sboxMinValue,sboxMaxValue);
sbox->setSuffix(sboxSuffixStr);
sbox->setPrefix(sboxPrefixStr);
sbox->setSingleStep(sboxSingleStep);
sbox->setStepType(sboxStepType);
sbox->setValue(sboxInitValue);
return sbox;
}
  1. 将模型中的数据赋值给编辑器
void Delegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
auto value = index.model()->data(index, Qt::EditRole);
QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
spinBox->setValue(value.toInt());
}
  1. 将编辑器的值赋值给模型
void Delegate::setModelData(QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index) const
{
QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
QVariant value = spinBox->value();
model->setData(index, value, Qt::EditRole);
}
  1. 更新编辑器的位置和大小
void Delegate::updateEditorGeometry(QWidget *editor,
const QStyleOptionViewItem &option,
const QModelIndex &/* index */) const
{
editor->setGeometry(option.rect);
}

这四个是主要的函数,实现这4个函数,说明我们已经完成95%了。

具体源文件如下

delegate.cpp

#include "delegate.h"
#include <QSpinBox>
Delegate::Delegate(QObject *parent): QStyledItemDelegate(parent)
{ } QWidget *Delegate::createEditor(QWidget *parent, const QStyleOptionViewItem &/*option*/, const QModelIndex &index) const
{
QSpinBox *sbox = new QSpinBox(parent);
sbox->setRange(sboxMinValue,sboxMaxValue);
sbox->setSuffix(sboxSuffixStr);
sbox->setPrefix(sboxPrefixStr);
sbox->setSingleStep(sboxSingleStep);
sbox->setStepType(sboxStepType);
sbox->setValue(sboxInitValue);
return sbox;
} void Delegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
auto value = index.model()->data(index, Qt::EditRole);
QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
spinBox->setValue(value.toInt());
} void Delegate::setModelData(QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index) const
{
QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
QVariant value = spinBox->value();
model->setData(index, value, Qt::EditRole); } void Delegate::updateEditorGeometry(QWidget *editor,
const QStyleOptionViewItem &option,
const QModelIndex &/* index */) const
{
editor->setGeometry(option.rect);
} void Delegate::setSboxMaxValue(const int max)
{
sboxMaxValue = max;
} void Delegate::setSboxMinValue(const int min)
{
sboxMinValue = min;
} void Delegate::setSboxPrefixStr(const QString &prefix)
{
sboxPrefixStr = prefix;
} void Delegate::setSboxSuffixStr(const QString &suffix)
{
sboxSuffixStr = suffix;
}
void Delegate::setSboxSingleStep(const int SingleStep)
{
sboxSingleStep = SingleStep;
} void Delegate::setSboxInitValue(const int initValue)
{
sboxInitValue = initValue;
}
void Delegate::setSboxStepType(QAbstractSpinBox::StepType st)
{
sboxStepType = st;
}

3.4 最后一步

我们需要在mainwindow.cpp中的init()调用delegate类实现委托。我们将QTableView的第一列设置为委托:

更新mainwindow.cpp中的init()函数

void MainWindow::init()
{
QStringList columnNames;
columnNames<<"QSpinBox"<<"QComboBox"<<"QCheckBox"<<"···"; model = new QStandardItemModel;
model->setRowCount(10);
model->setHorizontalHeaderLabels(columnNames);
ui->tableView->setModel(model); Delegate * sboxDelegate = new Delegate;
sboxDelegate->setSboxMinValue(0);
sboxDelegate->setSboxMaxValue(100);
sboxDelegate->setSboxSingleStep(2);
sboxDelegate->setSboxInitValue(10);
ui->tableView->setItemDelegateForColumn(0,sboxDelegate);
}

4 运行效果如下

5 QDoubleSpinBox委托

和实现QSpinBox委托相同,大家可以照葫芦画瓢,自己尝试编写。

6 思考

我们上面实现的QSpinBox委托,并不是一直显示在QTableView上的,而是需要我们单击时才会显示,有没有办法将QSpinBox一直悬停在QTableView上?当然是可以的,后面几篇文章我们会慢慢讲到。

7 源码

源码

都看到这里了,赏个关注吧!

QT中级(1)QTableView自定义委托(一)实现QSpinBox、QDoubleSpinBox委托的更多相关文章

  1. 自定义委托类型 - .Net自带委托类型

    委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递. 与其他的类不同,委托类具有一个签名,并且它只能对与其签名匹配的方法进行引用. 一.自定义委托类型 1.语法结构:访问修 ...

  2. Qt之界面(自定义标题栏、无边框、可移动、缩放)

    效果 自定义标题栏 titleBar.h #ifndef TITLEBAR_H #define TITLEBAR_H #include <QLabel> #include <QPus ...

  3. 链方法[C# 基础知识系列]专题三:如何用委托包装多个方法——委托链

    最近研究链方法,稍微总结一下,以后继续补充: 弁言: 上一专题分析了下编译器是如何来翻译委托的,从中间语言的角度去看委托,希望可以帮助大家进一步的理解委托,然而之前的分析都是委托只是封装一个方法,那委 ...

  4. 第十节:委托和事件(2)(泛型委托、Func和Action、事件及与委托的比较)

    一. 泛型委托 所谓的泛型委托,即自定义委托的参数可以用泛型约束,同时内置委托Func和Action本身就是泛型委托. 将上一个章节中的Calculator类中的方法用自定义泛型委托重新实现一下. p ...

  5. [C# 基础知识系列]专题三:如何用委托包装多个方法——委托链 (转载)

    引言: 上一专题介绍了下编译器是如何来翻译委托的,从中间语言的角度去看委托,希望可以帮助大家进一步的理解委托,然而之前的介绍都是委托只是封装一个方法,那委托能不能封装多个方法呢?因为生活中经常会听到, ...

  6. C# 委托链、多路广播委托

    委托链.多路广播委托:也就是把多个委托链接在一起,我们把链接了多个方法的委托称为委托链或多路广播委托 例: class HelloWorld { //定义委托类型 delegate void Dele ...

  7. Kotlin属性委托系统总结与提供委托详解

    属性委托总结回顾: 在前三次已经将Kotlin委托相关的知识点进行了完整的学习了,具体博文如下: https://www.cnblogs.com/webor2006/p/11369019.html h ...

  8. Qt 学习之路 :自定义只读模型

    model/view 模型将数据与视图分割开来,也就是说,我们可以为不同的视图,QListView.QTableView和QTreeView提供一个数据模型,这样我们可以从不同角度来展示数据的方方面面 ...

  9. Qt中的QTableView 中的列放入Widget

    QTableView是Qt中Model View理念的框架,View只展现数据,所以通过互交修改编辑数据,需要用到委托这个概念Delegate. 所以基本思路是继承QItemDelegate这个类,然 ...

  10. Qt——用于表格QTableView的模型

    如果想使用表格来呈现数据,Qt提供了一个方便的部件QTableWidget,但是直接用它实现一些功能可能比较困难.这里将介绍一种强大.灵活的方式来操作表格. 一.模型/视图架构 在这个架构中,模型用于 ...

随机推荐

  1. NOIP模拟测试A3

    A. 谜之阶乘 题目是让我们把 \(n\) 分解成两个阶乘的商,本来想推个式子什么的,结果发现推不出来. 我们知道,阶乘的增长速率非常的快啊!那么这个 \(b - a\) 的值肯定不会太大,我们可以暴 ...

  2. 学习 HBase

    1 由来 HBase 应大数据而生,是Apache Hadoop项目孵化而来的一种NoSQL数据库,HBase 是 Hadoop Database 的简称. 它的出现有以下几个原因: 大数据时代的到来 ...

  3. js: 获取Blob的值

    this.ws.onmessage = async (msg) => { console.log('从服务端获取到了数据') // 从真正服务端发送过来的原始数据时在msg中的data字段 co ...

  4. 人工智能如何应对 DevOps 监控和可观测性挑战

    自 ChatGPT 横空出世之后,AIGC 已成为不可逆转的时代浪潮.在之前的文章中,我们介绍了DevOps 领域中AI的用例,需要回顾可以点击下方链接.在本篇文章中,我将简单聊聊人工智能(AI)如何 ...

  5. 原来ES7~12分别增加了这些属性呀

    ES6也称为ES2015,于2015年发布,此后每年都有新增一些属性,分别命名为ES7~12,发布的年份分别对应2016年到2021年 ES7 includes方法 数组中新增了includes方法, ...

  6. docker安装phpmyadmin

    下载docker镜像 docker pull phpmyadmin/phpmyadmin 创建容器 # 假设MySQL服务器的地址为:192.168.0.10,端口3306 # 通过3360端口访问p ...

  7. 二代水务系统架构设计分享——DDD+个性化

    系统要求 C/S架构的单体桌面应用,可以满足客户个性化需求,易于升级和维护.相比于一代Winform,界面要求美观,控件丰富可定制. 解决方案 依托.Net6开发平台,采用模块化思想设计(即分而治之的 ...

  8. Kali开机启动模式修改

    kali Linux安装之后默认启动图形化界面,为了减轻系统负担,可以修改启动进入字符界面. 具体步骤如下: 1.打开引导配置文件 vim /etc/default/grub 2.修改GRUB_CMD ...

  9. Linux 内核设备树时钟绑定

    这种绑定依然处于开发中,并且基于 benh[1] 的一些实验性工作. 时钟信号源可以由设备树中的任何节点表示.这些节点被指定为时钟提供者.时钟消费者节点使用 phandle 和时钟指示符对将时钟提供者 ...

  10. 《CTFshow-Web入门》03. Web 21~30

    @ 目录 web21 题解 原理 web22 题解 原理 web23 题解 原理 web24 题解 原理 web25 题解 原理 web26 题解 web27 题解 web28 题解 web29 题解 ...