基于QTableView中的MVD代理添加总结

news2025/1/13 17:26:45

目录

1、Qt中MVD说明

1.1 View

1.2 Delegate

1.3 Model/View的基本原理

2、代码是现实示例

2.1 设置样式文件

2.2 set base attribute

 2.3 设置model

2.4 设置表头

2.5 设置数据     

2.6 添加代理控件

2.6.1 添加 QSpinBox 代理 

2.6.2 添加 QComboBox 代理

2.6.3 添加 QPushButton 代理

2.6.4 添加 CheckBox 代理 

2.6.5 添加 Pixmap 代理

2.6.6 添加 LineEdit 代理

2.6.7 添加 ReadOnly 代理

2.6.8 添加 Text 代理 

2.6.9 添加 QProcessBar 代理

2.6.10 添加 DateEdit 代理

2.6.11 添加 添加自定义窗口 代理 

2.6.12 添加 DoubleProcessBar 代理

2.7 获取某一单元格数据 



开发过程中进程使用MVD模型,添加各种代理控件,本文在此基础上整理一些数据模型代理,包括:QPushbutton、QLineEdit、QPixmap、QChecledBox、QComboBox、QSpinBox、QProcessBar、只读列、自定义窗口等共13种代理方式,如图所示:

在此之前,先来说明一下对MVD做一简单说明:

1、Qt中MVD说明

        在传统的MVC模型中,view用于向用户展示model数据。但是,Qt提供的并不是MVC架构,而是一个model/view的设计(也就是说,没有包含一个完整而独立的组件用于管理用户的交互)。一般来说,view仅仅是作用于model数据的展示和用户输入的处理,而不应该去做其他的工作。在这种结构中,为了获得对用户输入控制的灵活性,就将这种交互工作交给了delegate完成(也就是“委托”)。简单来说,就是view将用户输入委托给delegate处理,而不自己去处理。这些组件提供一种输入能力,并且能够在某些view中提供这种交互情形下的渲染,比如在table中双击某单元格进行编辑等。

1.1 View

        QListView、QTreeView、QTableView

1.2 Delegate

        Delegate可以用于渲染内容,这是通过paint() 和sizeHint()函数来完成的。但是对于一些简单的基于组件的delegate,可以通过继承QItemdelegate或者QStyledItemDelegate 来实现,而不需要重写虚函数。

Qt提供的标准组件中使用QItemDelegate提供编辑功能的支持。这种默认的实现被用在QListView,QTableView和QTreeView中。View实用的delegate可以通过itemDelegate()函数获得,其中,setItemDelegate()函数则可以为一个标准组件设置自定义的delegate.

在Qt4.4之后提供QItemDelegate/QStyledItemDelegate ,可以把控件设置成只读、表格的某一列制定自己需要的控件。默认的委托是QStyledItemDelegate。这两个类可以被相互替代,给view组件提供绘制和编辑功能。主要区别在于,QStyledItemDelegate使用当前的风格(style)去绘制组件,所以当需要设置 qt style sheet时建议使用QStyleItemDelegaet作为父类。使用这两个类的代码是一样的,除了需要使用style进行绘制的部分。

注意:绘制和向视图提供编辑器的方式,但使用起来感觉区别不是很大,之前使用过代理第一时间想到的是重写代理,实现虚函数,在虚函数中创建自己想要的控件并返回就OK了,但是运行程序时发现并没有默认显示出来,只有在编辑的时候显示(也就是双击的时候),这种方式用在输入限制的时候感觉比较合适(对此,官方文档是这样解释的:The QStyledItemDelegate class provides display and editing facilities for data items from a model.)。也就是说,如果想要在load的时候就显示出来控件,必须写在void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;里;如果控件需要有相应的动作,就需要写在editorEvent

        如果delegate没有支持为你的数据类型进行绘制,或者你希望自己绘制item,那么就可以继承QStyleItemDelegate类,并且重写paint()或者还需要重写sizeHit()函数。paint()函数会被每一个item独立调用,而sizeHint()函数则可以定义每一个item的大小。在重写paint()函数的时候,通常需要用if语句找到你需要进行渲染的诗句类型并进行绘制,其他的数据类型需要调用父类的实现进行绘制。

继承QStyledItemDelegate需要实现以下函数:

class MyDelegate: public QStyledItemDelegate
{
    //创建你编辑时候的控件,返回修改数据的组件
    QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const  QModelIndex &index) const;

    //编辑的时候设置数据到上面创建的editor中。
    void setEditorData(QWidget *editor, const QModelIndex &index) const; 

    //编辑完成,保存数据到model中
    void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const;

    //设置编辑控件的位置和大小、样式等(保证editor显示在item view的合适位置以及大小)
    void updateEditorGeometry ( QWidget * editor, const QStyleOptionViewItem & option, const QModelIndex & index ) const;
}

例如,添加一个进度条控件:

void WidgetDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    if (index.column() == 1) {
        int progress = index.data().toInt();
        QStyleOptionProgressBar progressBarOption;
        progressBarOption.rect = option.rect;
        progressBarOption.minimum = 0;
        progressBarOption.maximum = 100;
        progressBarOption.progress = progress;
        progressBarOption.text = QString::number(progress) + "%";
        progressBarOption.textVisible = true;
        QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption, painter);
      } else
        QStyledItemDelegate::paint(painter, option, index);
}

1.3 Model/View的基本原理

1、数据(Data)是实际的数据,如数据库的一个数据表或 SQL查询结果,内存中的一个StringList,或磁盘文件结构等。

2、视图或视图组件(View)是屏幕上的界面组件,视图从数据模型获得每个数据项的模型索引(model index),通过模型索引获取数据,然后为界面组件提供显示数据,Qt提供一些现成的数据视图组件,如QListView、QTreeView 和QTableView等。

3、模型或数据模型(Model)与实际数据通信,并为视图组件提供数据接口。它从原始数据提取需要的内容,用于视图组件进行显示和编辑。Qt中有一些预定义的数据模型,如QStringListModel
可作为StringList的数据模型,QSqlTableModel 可以作为数据库中一个数据表的数据模型。

        模型(Model)与数据源(Data)通信;视图(View)从模型(Model)中获取模型索引;在标准视图中,代理(delegate)渲染数据项。编辑项时,代理将直接使用模型索引(model index)与模型通信。模型、视图和代理之间使用信号和槽通信。当源数据发生变化时,数据模型发射信号通知视图组件:当用户在界面上操作数据时,视图组件发射信号表示这些操作信息;当编辑数据时,代理发射信号告知数据模型和视图组件编辑器的状态。

所有的基于项数据(item data)的数据模型(Model)都基于QAbstractltemModel类,此类定义了视图和代理访问数据的接口。数据本身不必存储在模型中;它可以保存在由单独的类、文件、数据库或其他应用程序组件提供的数据结构或存储库中。QabstracteModel提供了一个数据接口,该接口足够灵活,可以处理以table、list和tree的形式表示数据的视图。

Qt提供了一些现成的模型,可用于处理数据项:

  • QStringListModel 用于处理QString列表的数据模型类
  • QStandardItemModel 标准的基于项数据的数据模型类,管理更复杂的树结构,每个项数据内都可以包含任意类型的数据
  • QFileSystemModel 提供有关本地文件系统中的文件和目录的信息,文件系统模型类
  • QSqlQueryModel 用于数据库sql查询结果的数据模型类
  • QSqlTableModel 用于数据库中一个数据表的数据模型类
  • QSqlRelationalTableModel 用于关系型数据表的数据模型类
  • QSortFilterProxyModel 与其他数据模型结合,提供排序和过滤功能的数据模型类

如果这些标准模型不符合您的要求,您可以将QAbstractItemModel、QAbstractListModel或QAbstractTableModel子类化,以创建自己的自定义模型。

一般需要实现的子类为:

//获得模型的行数
int rowCount(const QModelIndex &parent) const;
//获得模型的列数
int columnCount(const QModelIndex &parent) const;
//向模型中设置数据
bool setData(const QModelIndex &index, const QVariant &value, int role );
//获得模型的数据
QVariant data(const QModelIndex &index, int role) const;
//设置模型的标题
QVariant headerData(int section, Qt::Orientation orientation, int role ) const;

2、代码是现实示例

2.1 设置样式文件

QString qssData = nullptr;
QFile fileqss(":/qss/QSSUITableView");
if(fileqss.open(QFile::ReadOnly))
{
        qssData = fileqss.readAll();
        fileqss.close();
}
ui->tableView->setStyleSheet(qssData);

2.2 set base attribute

    ui->tableView->verticalHeader()->hide();                                                   // 隐藏垂直头
    ui->tableView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);                       // 隐藏水平头
    //ui->tableView->horizontalHeader()->setStretchLastSection(true);                          // 设置随后一列拉伸
    ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive);         // 设置列平均分配
    //ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);  // 设置TreeWidget水平滚动和自适应宽度
    //ui->tableView->setColumnWidth(headersList.count() - 1, TITLE_FIXED_HEIGHT);              // 设置最后一列固定
    //ui->tableView->setSelectionMode(QAbstractItemView::SelectionMode::SingleSelection);      // 行单选
    ui->tableView->setSelectionMode(QAbstractItemView::SelectionMode::MultiSelection);         // 行多选 (单选QAbstractItemView::SingleSelection 多选:QAbstractItemView::MultiSelection)
    ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);                         // 不可编辑
    ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows);                        // 设置选中模式为整行
    ui->tableView->setShowGrid(false);                                                         // 显示/隐藏网格线
    setFocusPolicy(Qt::FocusPolicy::NoFocus);                                                  // 设置选中之后无虚线焦点
    //horizontalHeader()->setMinimumSectionSize(100);                                          // 设置最小列宽
    //horizontalHeader()->setMaximumSectionSize(100);                                          // 设置最大列宽
    ui->tableView->verticalHeader()->setDefaultSectionSize(25);                                 // 可以设置tableview所有列的默认行高为15。
    //horizontalHeader()->setDefaultSectionSize(15);                                            // 可以设置tableview所有行的默认列宽为15。
    ui->tableView->setWordWrap(false);                                                         // 设置不自动换行
    setMouseTracking(true);                                                                     // 设置鼠标追踪

    // 设置第0列固定宽度
    /*
    ui->tableView->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Fixed);
    ui->tableView->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Stretch);
    ui->tableView->horizontalHeader()->setSectionResizeMode(2, QHeaderView::Fixed);
    ui->tableView->horizontalHeader()->setSectionResizeMode(3, QHeaderView::Fixed);
    ui->tableView->horizontalHeader()->setSectionResizeMode(4, QHeaderView::Fixed);
    ui->tableView->horizontalHeader()->setSectionResizeMode(5, QHeaderView::Fixed);
    ui->tableView->setColumnWidth(0, 50);
    ui->tableView->setColumnWidth(2, 150);
    ui->tableView->setColumnWidth(3, 150);
    ui->tableView->setColumnWidth(4, 150);
    ui->tableView->setColumnWidth(5, 150);
    */

 2.3 设置model

    model = new QStandardItemModel;
    ui->tableView->setModel(model);

2.4 设置表头

    QStringList headerList;
    headerList<<"姓名"<<"QSpinBox"<<"QComboBox"<<"QPushButton"<<"CheckBox"<<"QPixmap"<<"QLineEdit"<<"ReadOnly"<<"Text"<<"ProcessBar"<<"DateEdit"<<"CustomWidget"<<"pDoubleProcessBar";
    model->setHorizontalHeaderLabels(headerList);

2.5 设置数据     

    model->setItem(0,0,new QStandardItem("张三"));
    model->setItem(1,0,new QStandardItem("李四"));
    model->setItem(2,0,new QStandardItem("王二"));
    model->setItem(3,0,new QStandardItem("小明同学"));

    model->setItem(0,1,new QStandardItem("1"));
    model->setItem(1,1,new QStandardItem("2"));
    model->setItem(2,1,new QStandardItem("3"));

    ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows);         // 选择一行

2.6 添加代理控件

2.6.1 添加 QSpinBox 代理 

    CUISpinBoxDelegate *pSpinBox = new CUISpinBoxDelegate(this);
    ui->tableView->setItemDelegateForColumn(1, pSpinBox);

2.6.2 添加 QComboBox 代理

    CUIComboBoxDelegate *pComboBox = new CUIComboBoxDelegate(this);
    ui->tableView->setItemDelegateForColumn(2, pComboBox);

2.6.3 添加 QPushButton 代理

    CUIMutipleButtonDeleagate *pMutipleBtn = new CUIMutipleButtonDeleagate(QStringList() << "修改" << "删除", this);

    ui->tableView->setItemDelegateForColumn(3, pMutipleBtn);

    connect(pMutipleBtn, &CUIMutipleButtonDeleagate::editData, [&](){
        QMessageBox::information(this, "提示", "这是一个编辑按钮");
    });
    connect(pMutipleBtn, &CUIMutipleButtonDeleagate::deleteData, [&](){
        QMessageBox::information(this, "提示", "这是一个删除按钮");
    });

2.6.4 添加 CheckBox 代理 

    /*CUITableHeaderView **/pTableHeaderView = new CUITableHeaderView(Qt::Horizontal, ui->tableView);

    connect(pTableHeaderView, &CUITableHeaderView::stateChanged, this, &MainWindow::headerStateChangedSlot);
    connect(model, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(itemChangedSlot(QStandardItem*)));

    ui->tableView->setHorizontalHeader(pTableHeaderView);

    CUICheckBoxDelegate *pCheckedBox = new CUICheckBoxDelegate(this);
    ui->tableView->setItemDelegateForColumn(4, pCheckedBox);

2.6.5 添加 Pixmap 代理

    CUIPixmapDelegate *pPixmap = new CUIPixmapDelegate(this);
    ui->tableView->setItemDelegateForColumn(5, pPixmap);

2.6.6 添加 LineEdit 代理

CUILineEditDelegate *pLineEdit = new CUILineEditDelegate(this);

2.6.7 添加 ReadOnly 代理

    CUIOnlyReadDelegate *pReadOnly = new CUIOnlyReadDelegate(this);
    ui->tableView->setItemDelegateForColumn(7, pReadOnly);

2.6.8 添加 Text 代理 

    CUITextDelegate *pLabel = new CUITextDelegate(this);
    ui->tableView->setItemDelegateForColumn(8, pLabel);

2.6.9 添加 QProcessBar 代理

    CUIProcessBarDelegate *pProcessBar = new CUIProcessBarDelegate();
    ui->tableView->setItemDelegateForColumn(9, pProcessBar);
    
    QModelIndex index = model->index(0, 9, QModelIndex());
    model->setData(index,29);

2.6.10 添加 DateEdit 代理

    CUIDateEditDelegate *pDateEdit = new CUIDateEditDelegate();
    ui->tableView->setItemDelegateForColumn(10, pDateEdit);

2.6.11 添加 添加自定义窗口 代理 

    CUICustomDelegate *pCustomWidget = new CUICustomDelegate(this);
    ui->tableView->setItemDelegateForColumn(11, pCustomWidget);

2.6.12 添加 DoubleProcessBar 代理

    CUIDoubleProcessBarDelegate *pDoubleProcessBar = new CUIDoubleProcessBarDelegate(this);
    ui->tableView->setItemDelegateForColumn(12, pDoubleProcessBar);

2.7 获取某一单元格数据 

    //model->index(0, 1).data();

详细代码下载

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/444088.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【JS】vis.js使用之vis-timeline使用攻略,vis-timeline在vue3中实现时间轴、甘特图

vis.js使用之vis-timeline使用攻略&#xff0c;vis-timeline实现时间轴、甘特图 1、vis-timeline简介2、安装插件及依赖3、简单示例4、疑难问题集合1. 中文zh-cn本地化2. 关于自定义class样式无法被渲染3. 关于双向数据绑定 vis.js是一个基于浏览器的可视化库&#xff0c;它提供…

深度探索vector

vector是什么 &#xff1f; vector就是一个可以自动扩充的array。 源码解析 vector主要是通过三个指针来维护的&#xff0c;分别是起点&#xff0c;当前终点&#xff0c;以及当前最大空间 sizeof(vector对象) 3 * 指针大小 vector每当遇到空间不同的情况&#xff0c;都会…

Windows逆向安全(一)之基础知识(十三)

Switch语句 先前讲了分支结构的if else形式&#xff0c;除此之外还有一种分支结构&#xff1a;switch 此次就来以反汇编的角度研究switch语句&#xff0c;并与if else进行比较 Switch语句的使用 有关Switch语句在vc6.0中生成的反汇编可分为4种情况&#xff0c;这4种情况的区…

不用科学上网,免费的GPT-4 IDE工具Cursor保姆级使用教程

1、Cursor 编辑器 可以直接官方网站下载&#xff1a;https://www.cursor.so/ &#xff08;这里以Mac为例&#xff09; 这是一款与OpenAI合作并且基于GPT4的新一代辅助编程神器&#xff0c;它支持多种文件类型&#xff0c;支持格式化文本、多种主题、多语言语法高亮、快捷键设…

react-7 组件库 Ant Design Mobile(移动端)

1.安装组件库 npm install --save antd-mobile 常用组件 tabbar 底部导航 Swiper 轮播图&#xff08;走马灯&#xff09; NavBar&#xff08;顶部返回累&#xff09; 配合 Dialog&#xff0c;Toast InfiniteScroll 无限滚动&#xff08;实现下拉刷新&#xff09; Skeleto…

ROS学习第九节——服务通信

1.基本介绍 服务通信较之于话题通信更简单些&#xff0c;理论模型如下图所示&#xff0c;该模型中涉及到三个角色: ROS master(管理者)Server(服务端)Client(客户端) ROS Master 负责保管 Server 和 Client 注册的信息&#xff0c;并匹配话题相同的 Server 与 Client &#…

远程控制电脑的软件哪个比较好用

有多种软件选项可用于远程控制计算机&#xff0c;最适合您的软件选项取决于您的具体需要和要求。 以下是一些最流行的远程控制软件选项及其功能和优势&#xff1a; TeamViewer TeamViewer 是使用最广泛的远程控制软件选项之一。 它具有用户友好的界面&#xff0c;并提供文件传…

Vue核心 Vue简介 初识

Vue核心 Vue简介 初识 1.1.Vue核心 Vue简介 初识 1.1.1.Vue核心 Vue简介 初识 英文官网 中文官网 1.1.2.介绍与描述 Vue 是一套用来动态构建用户界面的渐进式JavaScript框架 构建用户界面&#xff1a;把数据通过某种办法变成用户界面渐进式&#xff1a;Vue可以自底向上逐层…

YOLO V8实战入门篇 | Anaconda3 | ultralytics

目录 一、虚拟环境1.1 Anaconda3 安装1.2 创建适用YOLO V8的虚拟环境 二、YOLO v82.1 YOLO v8简介2.2 下载YOLO v8源码2.3 安装依赖 三、运行目标检测模型 一、虚拟环境 1.1 Anaconda3 安装 https://blog.csdn.net/weixin_42855758/article/details/122795125 参考这个链接&a…

NDK OpenCV 身份证信息离线识别

NDK系列之OpenCV 身份证信息离线识别技术实战&#xff0c;本节主要是通过OpenCV C库&#xff0c;实现身份证信息识别&#xff0c;如身份证号码识别&#xff0c;本节使用到的技术点同样适用于车牌号识别、银行卡号码识别等。 实现效果&#xff1a; 本节主要内容&#xff1a; 1…

数据库底层运行原理之——事务管理器

一般所有关系型数据库内部都有自己的事务机制&#xff0c;进程是如何保证每个查询在自己的事务内执行的&#xff0c;通过这篇文章来简单介绍一下。 我们可以理解为数据库是由多种相互交互的组件构成的&#xff0c;数据库一般可以用如下图形来理解&#xff1a; 事务管理器就是今…

两种方法,计算带地形起伏的地表面积

很多同学会经常计算占地面积, 就会用到投影面积计算和椭球体面积计算; 还有一些,需要去计算表面积, 也就是带地形起伏的地表面积, 这......咋办呢? 我们来介绍两种方法, 计算下面这个区域的地表面积—— 两种方法各有优势, 大家各取所需 方法一:表面体积工具 这…

【hello Linux】进程优先级

目录 1. 基本概念 2. 查看系统进程&#xff1a;&#xff08;包括优先级&#xff09; 2.1 使用命令查看系统进程 2.2 各字段分析 2.3 优先级的修正解释 2.4 使用 top 命令修改优先级 其他概念 Linux&#x1f337; 1. 基本概念 进程的优先权&#xff08; priority&#xff09;&…

Java版企业电子招投标系统源代码之电子招投标系统建设的重点和未来趋势

项目说明 随着公司的快速发展&#xff0c;企业人员和经营规模不断壮大&#xff0c;公司对内部招采管理的提升提出了更高的要求。在企业里建立一个公平、公开、公正的采购环境&#xff0c;最大限度控制采购成本至关重要。符合国家电子招投标法律法规及相关规范&#xff0c;以及…

网工神器:PNETLab模拟器踩坑过程(一)

0、前言 由于工作需要&#xff0c;想测试一下SD-WAN&#xff0c;手边既没有测试环境又没有测试设备。突然想到为什么不用模拟器测试。经过我一番操作好像发现了新大陆&#xff0c;没想到模拟器的世界发生了翻天覆地的变化。真是“一日学习一日功&#xff0c;一日不学十日空”。…

【IoT】以一款实际产品为例,来谈谈如何做商业计划分析

本篇内容以笔者早期刚转型做产品时,实际负责的一款产品为例,来谈谈如何做产品的商业计划分析。 首先简单介绍一下这款产品: 这是一款电子便签产品,目的是为了替换纸质便签,增加一些智能化的提醒控制。 该产品通过蓝牙与手机端连接,应用端配置好提醒信息后一键同步至产…

鼠标悬停发光按钮,流转边框

提示&#xff1a;css 动画实现&#xff0c;鼠标悬停发光按钮&#xff0c;流转边框。鼠标border可以旋转 前言 提示&#xff1a;以下是本篇文章的代码内容,供大家参考,相互学习 一、html代码 <!DOCTYPE html> <html><head><meta http-equiv"content…

企业信息化建设该怎么做?方向和手段都在这了

企业信息化建设该怎么做&#xff1f; 如果现在是十年前&#xff0c;我一定会说&#xff0c;做信息化需要寻找熟悉不同编程语言、有经验的程序员。 但是现在&#xff0c;如果不是特别复杂的信息化系统&#xff0c;其实公司完全可以使用零代码平台自主开发&#xff0c;不需要再…

[计算机图形学]光线追踪:加速结构(前瞻预习/复习回顾)

一、前言 上篇我们提到了&#xff0c;如果在光线追踪中&#xff0c;我们真的用每个像素发出的光线&#xff0c;以及在场景中弹射之后的光线与场景中的许多模型的上千万个三角形求交那将是一个非常慢的计算过程&#xff0c;所以&#xff0c;本篇我们将介绍一些加速结构来加速这个…

【FTP服务】

目录 一、FTP服务二、FTP服务器安装配置FTP服务的安装匿名访问开启防火墙设置本地用户修改配置文件 以图形化的格式来写入文件 三、设置白名单&#xff0c;黑名单用户 一、FTP服务 作用: 是用来传输文件的协议 端口: FTP服务器默认使用TCP协议的20、21端口与客户端进行通信 2…