QT中级(1)QTableView自定义委托(一)实现QSpinBox、QDoubleSpinBox委托
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 第二步
- 我们首先创建一个类
Delegate继承QStyledItemDelegate,同时定义以下四个函数:
QWidget * createEditor(..)
void setEditorData(...)
void setModelData(...)
void updateEditorGeometry(...)
这四个函数的作用以及意义,详见:《QT(7)-初识委托》这里不在赘述。
- 创建一些 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);
这里我定义了很多参数,实际应用的时候有些参数并用不到,大家根据需求定义。
- 创建给这些参数初始化的函
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 第三步
下面我们逐个实现这四个虚函数函数:
- 创建编辑器
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);
}
这四个是主要的函数,实现这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委托的更多相关文章
- 自定义委托类型 - .Net自带委托类型
委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递. 与其他的类不同,委托类具有一个签名,并且它只能对与其签名匹配的方法进行引用. 一.自定义委托类型 1.语法结构:访问修 ...
- Qt之界面(自定义标题栏、无边框、可移动、缩放)
效果 自定义标题栏 titleBar.h #ifndef TITLEBAR_H #define TITLEBAR_H #include <QLabel> #include <QPus ...
- 链方法[C# 基础知识系列]专题三:如何用委托包装多个方法——委托链
最近研究链方法,稍微总结一下,以后继续补充: 弁言: 上一专题分析了下编译器是如何来翻译委托的,从中间语言的角度去看委托,希望可以帮助大家进一步的理解委托,然而之前的分析都是委托只是封装一个方法,那委 ...
- 第十节:委托和事件(2)(泛型委托、Func和Action、事件及与委托的比较)
一. 泛型委托 所谓的泛型委托,即自定义委托的参数可以用泛型约束,同时内置委托Func和Action本身就是泛型委托. 将上一个章节中的Calculator类中的方法用自定义泛型委托重新实现一下. p ...
- [C# 基础知识系列]专题三:如何用委托包装多个方法——委托链 (转载)
引言: 上一专题介绍了下编译器是如何来翻译委托的,从中间语言的角度去看委托,希望可以帮助大家进一步的理解委托,然而之前的介绍都是委托只是封装一个方法,那委托能不能封装多个方法呢?因为生活中经常会听到, ...
- C# 委托链、多路广播委托
委托链.多路广播委托:也就是把多个委托链接在一起,我们把链接了多个方法的委托称为委托链或多路广播委托 例: class HelloWorld { //定义委托类型 delegate void Dele ...
- Kotlin属性委托系统总结与提供委托详解
属性委托总结回顾: 在前三次已经将Kotlin委托相关的知识点进行了完整的学习了,具体博文如下: https://www.cnblogs.com/webor2006/p/11369019.html h ...
- Qt 学习之路 :自定义只读模型
model/view 模型将数据与视图分割开来,也就是说,我们可以为不同的视图,QListView.QTableView和QTreeView提供一个数据模型,这样我们可以从不同角度来展示数据的方方面面 ...
- Qt中的QTableView 中的列放入Widget
QTableView是Qt中Model View理念的框架,View只展现数据,所以通过互交修改编辑数据,需要用到委托这个概念Delegate. 所以基本思路是继承QItemDelegate这个类,然 ...
- Qt——用于表格QTableView的模型
如果想使用表格来呈现数据,Qt提供了一个方便的部件QTableWidget,但是直接用它实现一些功能可能比较困难.这里将介绍一种强大.灵活的方式来操作表格. 一.模型/视图架构 在这个架构中,模型用于 ...
随机推荐
- 【爬虫案例】用Python爬取知乎热榜数据!
目录 一.爬取目标 二.编写爬虫代码 三.同步讲解视频 3.1 代码演示视频 3.2 详细讲解视频 四.获取完整源码 一.爬取目标 您好,我是@马哥python说,一名10年程序猿. 本次爬取的目标是 ...
- Java_Day16_作业
A:简答题 1.请把我们讲解过的所有类中的方法在API中找到,并使用自己的话进行描述 答案: Map public V put(K key, V value): public void clear() ...
- go build怎么使用
go build 是 Go 语言编译器的一个命令,用于将 Go 源代码文件编译成可执行的二进制文件.它是 Go 语言开发过程中常用的一个命令.以下是 go build 的基本使用方法: go buil ...
- 【技术实战】Vue技术实战【五】
需求实战一 效果展示 代码展示 <template> <div class="home-component"> <div class="pr ...
- [Python]数组基础
在python中,一般使用列表表示数组.例如: 一维数组 arr1 = [1,2,3,4] 二维数组 arr2 = [[1,2,3,4],[5,6,7,8]] 数组的常用操作 追加 利用append( ...
- 基于Pair-wise和CrossEncoder训练单塔模型
本文分享自华为云社区<语义检索系统排序模块:基于ERNIE-Gram的Pair-wise和基于RocketQA的CrossEncoder训练单塔模型>,作者: 汀丶. 文本匹配任务数据每一 ...
- Vue项目打包后放到SpringBoot项目里注意点
- devops之Python编程-类的基础架构
Python中,可以通过关键字class来定义一个类.类是一种自定义数据类型,它可以包含属性(变量)和方法(函数).下面是一个示例: class MyClass: def __init__(self, ...
- 发布策略:蓝绿部署、金丝雀发布(灰度发布)、AB测试、滚动发布、红黑部署的概念与区别
蓝绿发布(Blue-Green Deployment) 蓝绿发布提供了一种零宕机的部署方式.不停老版本,部署新版本进行测试,确认OK,将流量切到新版本,然后老版本同时也升级到新版本.始终有两个版本同时 ...
- 分拣平台API安全治理实战 | 京东物流技术团队
导读 本文主要基于京东物流的分拣业务平台在生产环境遇到的一些安全类问题,进行定位并采取合适的解决方案进行安全治理,引出对行业内不同业务领域.不同类型系统的安全治理方案的探究,最后笔者也基于自己在金融领 ...