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. MyBatis理论

    MyBatis简介 MyBatis是什么? MyBatis是一款优秀的持久层框架,一个ORM(对象关系映射)框架,它支持定制化SQL.存储过程以及高级映射.MyBaits避免了几乎所有JDBC代码和手 ...

  2. 【技术积累】Vue中的核心概念【四】

    Vue的生命周期 Vue中的生命周期是指组件从创建到销毁的整个过程中,会触发一系列的钩子函数 Vue2中的生命周期 Vue2中的生命周期钩子函数是在组件的不同阶段执行的特定函数.这些钩子函数允许开发者 ...

  3. vim 配色调整

    ~/.vimrc " Configuration file for vim set modelines=0 " CVE-2007-2438 set number " se ...

  4. [golang]简单的文件上传下载

    前言 某次在客户内网传输数据的时候,防火墙拦截了SSH的数据包,导致没法使用scp命令传输文件,tcp协议和http协议也只放开了指定端口,因此想了个用http传输的"曲线救国"方 ...

  5. C#性能优化-树形结构递归优化

    前言 大家好,我是wacky,最近在工作中遇到一个有趣的问题,同事反馈说WPF中有一个树形结构的集合,在加载时会直接报堆栈溢出,一直没时间(懒得)看,导致很久了也没人解决掉.于是,组长就把这个&quo ...

  6. Unity UGUI的Image(图片)组件的介绍及使用

    UGUI的Image(图片)组件的介绍及使用 1. 什么是UGUI的Image(图片)组件? UGUI的Image(图片)组件是Unity引擎中的一种UI组件,用于显示2D图像.它提供了一种简单而灵活 ...

  7. Pytorch语法——torch.autograd.grad

    The torch.autograd.grad function is a part of PyTorch's automatic differentiation package and is use ...

  8. Python 基础面试第四弹

    1. Python中常用的库有哪些,作用分别是什么 requests: requests 是一个用于发送 HTTP 请求的库,它提供了简单而优雅的 API,可以轻松地发送 GET.POST.PUT.D ...

  9. Codeforces-1095E-Almost-Regular-Bracket-Sequence

    题意 给定一个长度为 \(n\) 的小括号序列,求有多少个位置满足将这个位置的括号方向反过来后使得新序列是一个合法的括号序列.即在任意一个位置前缀左括号的个数不少于前缀右括号的个数,同时整个序列左右括 ...

  10. WPF学习 - 用鼠标移动、缩放、旋转图片(1)

    1. 需求 其实我的需求很简单.就是想做一个图片查看器,可以通过鼠标来平移.缩放.旋转图片. 2. 解决思路: WPF中的UIElement提供了RenderTransform属性,用于承载各种Tra ...