当前位置: 首页 > news >正文

Qt model/view 理解 2

这是我对 Qt 的 model/view 内容理解的第二篇 blog,在第一篇文章中,介绍 QTableView 和 QAbstractTableModel,实现显示了对数据源的显示,但是显示的格式和修改的模式都是按照 View 控件的自显示方式。在此,使用 Qt 自带的 QStyledItemDelegate 类实现对特定行 / 列的显示 / 修改模式实现,实现过程中不出现对 item 的代码生成,对 item 的生成由程序自动完成。

在此同样以《c++ gui programming with Qt4》中的 trackEditor 例子作一讲解。

在此,我们首先应当考虑以下几个问题:

1)有一个代理类加到 View 中,处理特定的 View 内容。

2)代理类要完成以下几项工作:a)当用户修改数据时生成用户要求的控件(用户每次修改数据时在相应的位置都会生成控件,所以当控件用完后,应 del 释放资源)。b)设置在生成的修改控件中显示的内容。c)设置要写到 model 中的数据内容。d)设置当结束修改数据后,View 显示的内容。

在此我们需要实现以下 4 个类。

/**  
@brief 保存显示数据的类。
*/
class Track/**  
@brief 继承的委托类。
*/
class TrackDelegate : public QStyledItemDelegate/**  
@brief 继承的模型类。
*/
class TrackModel : public QAbstractTableModel/**  
@brief 用于组装显示的控件类。
*/
class TrackEditor : public QDialog

在此,Track TrackModel TrackEditor 的功能在 Qt model/view 理解 1 中做过介绍,在此只列出 code,不再过多介绍。在此主要介绍 TrackDelegate。

Track h 文件

#ifndef TRACK_H
#define TRACK_H#include <QString>/**@projectName   ItemView@author        qiaowei@date          2018-12-22@version       1.0@description   保存的音频数据,包括音频名称和时长
**/
class Track
{
public:explicit Track(const QString& title = "", int duration = 0);QString getTitle() const;void setTitle(const QString& title);int getDuration() const;void setDuration(int duration);private:/**@author        qioawei@date          2018-12-22@description   音频名称**/QString title_;/**@author        qioawei@date          2018-12-22@description   音频时长(单位:秒)**/int duration_;
};#endif // TRACK_H

Track.cpp

#include "track.h"Track::Track(const QString &title, int duration) :title_(title),duration_(duration)
{}QString Track::getTitle() const
{return title_;
}void Track::setTitle(const QString &title)
{title_ = title;
}int Track::getDuration() const
{return duration_;
}void Track::setDuration(int duration)
{duration_ = duration;
}

TrackModel.h

#ifndef TRACKMODEL_H#define TRACKMODEL_H#include <QWidget>
#include <QAbstractTableModel>
#include <QList>
#include "track.h"
#include <QObject>/**@brief 继承的模型类。
*/
class TrackModel : public QAbstractTableModel
{Q_OBJECTpublic:explicit TrackModel(QList<Track>* tracks, QObject* parent = 0);~TrackModel();virtual int rowCount(const QModelIndex &parent) const;virtual int columnCount(const QModelIndex &parent) const;virtual QVariant data(const QModelIndex &index, int role) const;virtual bool setData(const QModelIndex &index,const QVariant &value,int role);virtual Qt::ItemFlags flags(const QModelIndex &index) const;private:QList<Track>* tracks;
};#endif // TRACKMODEL_H

TrackEditor h 文件

#ifndef TRACKEDITOR_H#define TRACKEDITOR_H#include <QDialog>#include "track.h"QT_BEGIN_NAMESPACE
class QTableView;
class TrackModel;
class QAbstractTableModel;
QT_END_NAMESPACEnamespace Ui {
class TrackEditor;
}/**@brief 用于组装显示的控件类。
*/
class TrackEditor : public QDialog
{Q_OBJECTpublic:explicit TrackEditor(QList<Track>* tracks, QWidget *parent = 0);~TrackEditor();private:Ui::TrackEditor *ui;QTableView* tableView;TrackModel* model;//QAbstractTableModel* model;
};#endif // TRACKEDITOR_H

TrackDelegate h 文件

#ifndef TRACKDELEGATE_H#define TRACKDELEGATE_H#include <QObject>
#include <QStyledItemDelegate>QT_BEGIN_NAMESPACE
class QPainter;
QT_END_NAMESPACE/**@brief 继承的委托类。
*/
class TrackDelegate : public QStyledItemDelegate
{
public:explicit TrackDelegate(QObject* parent = 0);~TrackDelegate();virtual QWidget* createEditor(QWidget *parent,const QStyleOptionViewItem &option,const QModelIndex &index) const;virtual void setEditorData(QWidget* parent,const QModelIndex& index) const;virtual void setModelData(QWidget* editor,QAbstractItemModel* model,const QModelIndex& index) const;virtual void updateEditorGeometry(QWidget* editor,const QStyleOptionViewItem& option,const QModelIndex& index) const;virtual void paint(QPainter* painter,const QStyleOptionViewItem &option,const QModelIndex &index) const;virtual QSize sizeHint(const QStyleOptionViewItem &option,const QModelIndex &index) const;private:bool isRightColumn(const QModelIndex& index, const int column) const;
private slots:void commitAndCloseEditor();private:static const int columnNumber;
};#endif // TRACKDELEGATE_H

TrackDelegate cpp 文件

#include "trackdelegate.h"
#include <QTimeEdit>
#include <QPainter>
#include <QApplication>#include "trackmodel.h"const int TrackDelegate::columnNumber = 1;TrackDelegate::TrackDelegate(QObject* parent) :QStyledItemDelegate(parent)
{}TrackDelegate::~TrackDelegate()
{}QWidget* TrackDelegate::createEditor(QWidget *parent,const QStyleOptionViewItem &option,const QModelIndex &index) const
{if (isRightColumn(index, TrackDelegate::columnNumber)) {QTimeEdit *timeEdit = new QTimeEdit(parent);timeEdit->setDisplayFormat("hh:mm");//当控件结束编辑内容时,触发释放资源connect(timeEdit, &QTimeEdit::editingFinished,this, &TrackDelegate::commitAndCloseEditor);//int secs = index.model()->data(index, Qt::DisplayRole).toInt();int secs = index.model()->data(index, Qt::EditRole).toInt();QTime time(secs / 60, secs % 60);timeEdit->setTime(time);return timeEdit;} else {return QStyledItemDelegate::createEditor(parent,option,index);}
}void TrackDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{if ( !index.isValid()) {return;}QTimeEdit* timeEditor = qobject_cast<QTimeEdit*>(editor);if ( !timeEditor) {return;}if (isRightColumn(index, TrackDelegate::columnNumber)) {int secs = index.model()->data(index, Qt::EditRole).toInt();QTime time(secs / 60, secs % 60);timeEditor->setTime(time);} else {QStyledItemDelegate::setEditorData(editor, index);}
}void TrackDelegate::setModelData(QWidget *editor,QAbstractItemModel *model,const QModelIndex &index) const
{if ( !index.isValid()) {return;}QTimeEdit* timeEditor = qobject_cast<QTimeEdit*>(editor);if ( !timeEditor) {return;}if (isRightColumn(index, TrackDelegate::columnNumber)) {QTime time = timeEditor->time();int secs = time.hour() * 60 + time.minute();model->setData(index, secs, Qt::EditRole);} else {QStyledItemDelegate::setModelData(editor,model,index);}
}void TrackDelegate::updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option,const QModelIndex &index) const
{Q_UNUSED(index);editor->setGeometry(option.rect);
}void TrackDelegate::paint(QPainter *painter,const QStyleOptionViewItem &option,const QModelIndex &index) const
{if (isRightColumn(index, TrackDelegate::columnNumber)) {int secs = index.model()->data(index, Qt::EditRole).toInt();QString text = QString("%1:%2").arg(secs / 60, 2, 10, QChar('0')).arg(secs % 60, 2, 10, QChar('0'));//获取项风格设置QStyleOptionViewItem myOption = option;myOption.displayAlignment = Qt::AlignRight | Qt::AlignVCenter;painter->drawText(option.rect, text);} else {QStyledItemDelegate::paint(painter, option, index);}
}QSize TrackDelegate::sizeHint(const QStyleOptionViewItem &option,const QModelIndex &index) const
{return option.rect.size();
}void TrackDelegate::commitAndCloseEditor()
{QTimeEdit* editor = qobject_cast<QTimeEdit*>(sender());emit commitData(editor);emit closeEditor(editor);
}bool TrackDelegate::isRightColumn(const QModelIndex &index,const int column) const
{if ( !index.isValid()) {return false;}if (index.column() == column) {return true;} else {return false;}
}

createEditor 用于创建用户自己需要的显示数据控件。

setEditorData 用于设置显示控件中显示的具体数据信息。

setModelData 用户设置模型的数据,也可理解为当显示的数据发生变化后,用户 update 模型数据,保持显示 / 储存内容一致。

paint 由用户自己绘制要显示的内容信息(很重要,当你点击时间框修改时间,要改的内容为原显示内容并允许你修改,而不是数据变为 00:00,让你修改)。

commitAndCloseEditor 创建关于 commitData 和 closeEditor 的信号槽链接,保证当代理控件的数据修改完成后,释放信号,保存数据(保存数据步骤由系统自动完成)。

在此要求注意内容:

在 TrackModel 类中的 setData 方法应当注意,data 的值应从 value 得出而不是通过 model 的 data 得出,model 得出的数据是原来保存的,而不是用户修改的。

 

相关文章:

Qt model/view 理解 2

这是我对 Qt 的 model/view 内容理解的第二篇 blog&#xff0c;在第一篇文章中&#xff0c;介绍 QTableView 和 QAbstractTableModel&#xff0c;实现显示了对数据源的显示&#xff0c;但是显示的格式和修改的模式都是按照 View 控件的自显示方式。在此&#xff0c;使用 Qt 自带…...

【LeetCode热题100】--114.二叉树展开为链表

114.二叉树展开为链表 方法一&#xff1a;对二叉树进行先序遍历&#xff0c;得到各个节点被访问到的顺序&#xff0c;利用数组存储下来&#xff0c;然后在先序遍历之后更新每个节点的左右节点的信息&#xff0c;将二叉树展开为链表 /*** Definition for a binary tree node.* …...

Java | Maven(知识点查询)

文章目录 Maven知识速查1. Maven概述2. Maven的作用3. Maven的下载4. Maven的环境配置5. Maven 的基础组成5.1 Maven仓库5.1.1 本地仓库配置&#xff1a;5.1.2 中央仓库配置&#xff1a;5.1.3 镜像仓库配置 5.2 Maven坐标 6. Maven项目6.1 手工创建Maven项目6.2 自动构建项目 7…...

Vmware 静态网络配置

概述 仅主机模式&#xff08;VMware1&#xff09;&#xff1a;使用host-only的方式是不能和外界通信的&#xff0c;只能够和本机的物理网卡通信 桥接&#xff08;VMnet0&#xff09;&#xff1a;使用桥接的方式使得自己的虚拟机和自己的真实机网卡在同一个网段 NAT&#xff0…...

【数据结构--八大排序】之希尔排序

&#x1f490; &#x1f338; &#x1f337; &#x1f340; &#x1f339; &#x1f33b; &#x1f33a; &#x1f341; &#x1f343; &#x1f342; &#x1f33f; &#x1f344;&#x1f35d; &#x1f35b; &#x1f364; &#x1f4c3;个人主页 &#xff1a;阿然成长日记 …...

Linux中生成so库的文件引用另一个so库问题的解决

文章目录 一、问题介绍二、问题解决 一、问题介绍 由于项目需求&#xff0c;需要将一个“编译时引用了另一个动态链接库”的文件&#xff08;名为main.c&#xff09;&#xff0c;再编译成一个动态链接库。 简要说明一下&#xff0c;即原本的项目代码里&#xff0c;包含main.c…...

EDI是连接原始电子商务和现代电子商务的纽带

EDI是连接原始电子商务和现代电子商务的纽带。 EDI&#xff08;Electronic Data Interchange&#xff0c;电子数据交换&#xff09;是一种电子通信技术&#xff0c;用于在不同组织之间以结构化和标准化的方式交换业务文档和数据。EDI使企业能够更有效地与供应商、客户和合作伙…...

星宿UI2.4资源付费变现小程序源码 支持流量主

第一个小程序为星宿小程序 目前是最新版2.0 搭建星宿需要&#xff1a;备用域名 服务器 微信小程序账号 功能&#xff1a;文章展示 文章分类 资源链接下载 轮播图 直接下载附件功能 很多 很适合做资源类分享 源码下载&#xff1a;https://download.csdn.net/download/m0_6604…...

代码随想录训练营二刷第四十六天 | 完全背包 518. 零钱兑换 II 377. 组合总和 Ⅳ

代码随想录训练营二刷第四十六天 | 518. 零钱兑换 II 377. 组合总和 Ⅳ 一、518. 零钱兑换 II 题目链接&#xff1a;https://leetcode.cn/problems/coin-change-ii/ 思路&#xff1a;完全背包求组合数&#xff0c;递推公式dp[j]dp[j-nums[i]]。 求组合数&#xff0c;物品在外…...

python安装第三方模块方法

正常情况下安装python第三方模块没啥说的&#xff0c;但是由于python安装模块默认是在外网下载安装&#xff0c;牵扯外网网速问题&#xff0c;所以可以配置下使用国内某镜像源来下载模块 python -m pip install xxxxxxxxxxx 和 pip install xxxxxxxxxx 的命令都可下载安装第三…...

广西小贷公司设立及小贷牌照申请政策要求

关于广西小额贷款公司设立及小贷牌照申请&#xff0c;依据《关于小额贷款公司试点的指导意见》&#xff08;银监发〔2008〕23号&#xff09;&#xff1b;《广西壮族自治区小额贷款公司管理办法》&#xff08;桂政发〔2009〕71号&#xff09;&#xff1b;《广西壮族自治区人民政…...

PyTorch应用实战二:实现卷积神经网络进行图像分类

文章目录 实验环境MNIST数据集1.网络结构2.程序实现2.1 导入相关库2.2 构建卷积神经网络模型2.3 加载MNIST数据集2.4 训练模型 附&#xff1a;系列文章 实验环境 python3.6 pytorch1.8.0 import torch print(torch.__version__)1.8.0MNIST数据集 MNIST数字数据集是一组手写…...

面试系列 - Java常见算法(二)

目录 一、排序算法 1、插入排序&#xff08;Insertion Sort&#xff09; 2、归并排序&#xff08;Merge Sort&#xff09; 二、图形算法 1、最短路径算法&#xff08;Dijkstra算法、Floyd-Warshall算法&#xff09; Dijkstra算法 Floyd-Warshall算法 2、最小生成树算法&…...

Cortex-A9 架构

一、Cortex-A 处理器运行模式 Cortex-A9处理器有 9中处理模式&#xff0c;如下表所示&#xff1a; 九种运行模式 在上表中&#xff0c;除了User(USR)用户模式以外&#xff0c;其它8种运行模式都是特权模式&#xff0c;在特权模式下&#xff0c;程序可以访问所有的系统资源。这…...

【C语言】循环结构程序设计(第二部分 -- 习题讲解)

前言:昨天我们学习了C语言中循环结构程序设计&#xff0c;并分析了循环结构的特点和实现方法&#xff0c;有了初步编写循环程序的能力&#xff0c;那么今天我们通过一些例子来进一步掌握循环程序的编写和应用。 &#x1f496; 博主CSDN主页:卫卫卫的个人主页 &#x1f49e; &am…...

UGUI交互组件Toggle

一.Toggle对象的构造 Toggle和Button类似&#xff0c;是交互组件的一种 如果所示&#xff0c;通过菜单创建了两个Toggle&#xff0c;Toggle2中更换了背景和标记资源 对象说明Toggle含有Toggle组件的对象Background开关背景Checkmark开关选中标记Label名称文本 二.Toggle组件属…...

亲,您的假期余额已经严重不足了......

引言 大家好&#xff0c;我是亿元程序员&#xff0c;一位有着8年游戏行业经验的主程。 转眼八天长假已经接近尾声了&#xff0c;今天来总结一下大家的假期&#xff0c;聊一聊假期关于学习的看法&#xff0c;并预估一下大家节后大家上班时的样子。 1.放假前一天 即将迎来八天…...

【软件测试】自动化测试selenium(一)

文章目录 一. 什么是自动化测试二. Selenium的介绍1. Selenium是什么2. Selenium的特点3. Selenium的工作原理4. SeleniumJava的环境搭建 一. 什么是自动化测试 自动化测试是指使用软件工具或脚本来执行测试任务的过程&#xff0c;以替代人工进行重复性、繁琐或耗时的测试活动…...

Nginx实现动静分离

一、概述 1、什么是动静分离 动静分离是让动态网站里的动态网页根据一定规则把不变的资源和经常变的资源区分开来&#xff0c;动静资源做好了拆分以后&#xff0c;我们就可以根据静态资源的特点将其做缓存操作&#xff0c;这就是网站静态化处理的核心思路。 动静分离简单的概…...

【算法题】309. 买卖股票的最佳时机含冷冻期

题目&#xff1a; 给定一个整数数组prices&#xff0c;其中第 prices[i] 表示第 i 天的股票价格 。 设计一个算法计算出最大利润。在满足以下约束条件下&#xff0c;你可以尽可能地完成更多的交易&#xff08;多次买卖一支股票&#xff09;: 卖出股票后&#xff0c;你无法在…...

C++_核心编程_多态案例二-制作饮品

#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为&#xff1a;煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例&#xff0c;提供抽象制作饮品基类&#xff0c;提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!

5月28日&#xff0c;中天合创屋面分布式光伏发电项目顺利并网发电&#xff0c;该项目位于内蒙古自治区鄂尔多斯市乌审旗&#xff0c;项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站&#xff0c;总装机容量为9.96MWp。 项目投运后&#xff0c;每年可节约标煤3670…...

生成 Git SSH 证书

&#x1f511; 1. ​​生成 SSH 密钥对​​ 在终端&#xff08;Windows 使用 Git Bash&#xff0c;Mac/Linux 使用 Terminal&#xff09;执行命令&#xff1a; ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" ​​参数说明​​&#xff1a; -t rsa&#x…...

Linux-07 ubuntu 的 chrome 启动不了

文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了&#xff0c;报错如下四、启动不了&#xff0c;解决如下 总结 问题原因 在应用中可以看到chrome&#xff0c;但是打不开(说明&#xff1a;原来的ubuntu系统出问题了&#xff0c;这个是备用的硬盘&a…...

IT供电系统绝缘监测及故障定位解决方案

随着新能源的快速发展&#xff0c;光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域&#xff0c;IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选&#xff0c;但在长期运行中&#xff0c;例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...

使用 SymPy 进行向量和矩阵的高级操作

在科学计算和工程领域&#xff0c;向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能&#xff0c;能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作&#xff0c;并通过具体…...

网站指纹识别

网站指纹识别 网站的最基本组成&#xff1a;服务器&#xff08;操作系统&#xff09;、中间件&#xff08;web容器&#xff09;、脚本语言、数据厍 为什么要了解这些&#xff1f;举个例子&#xff1a;发现了一个文件读取漏洞&#xff0c;我们需要读/etc/passwd&#xff0c;如…...

基于TurtleBot3在Gazebo地图实现机器人远程控制

1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...

腾讯云V3签名

想要接入腾讯云的Api&#xff0c;必然先按其文档计算出所要求的签名。 之前也调用过腾讯云的接口&#xff0c;但总是卡在签名这一步&#xff0c;最后放弃选择SDK&#xff0c;这次终于自己代码实现。 可能腾讯云翻新了接口文档&#xff0c;现在阅读起来&#xff0c;清晰了很多&…...

免费数学几何作图web平台

光锐软件免费数学工具&#xff0c;maths,数学制图&#xff0c;数学作图&#xff0c;几何作图&#xff0c;几何&#xff0c;AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...