QT Mode/View之View
目录
概念
使用已存在的视图
使用模型
使用模型的多个视图
处理元素的选择
视图间共享选择
概念
在模型/视图架构中,视图从模型中获取数据项并将它们呈现给用户。数据的表示方式不必与模型提供的数据表示形式相似,而且可能与用于存储数据项的底层数据结构完全不同。
通过使用QAbstractItemModel提供的标准模型接口和QAbstractItemView提供的标准视图接口,以及使用通用方式表示数据项的模型索引,实现了内容与表现的分离。视图通常管理从模型中获得的数据的总体布局。它们可以自己渲染单个数据项,或者使用委托来处理渲染和编辑功能。
除了显示数据,视图还处理项目之间的导航,以及项目选择的一些方面。这些视图还实现了基本的用户界面功能,例如上下文菜单和拖放。视图可以为项目提供默认的编辑功能,也可以与委托一起提供自定义编辑器。
可以在没有模型的情况下构建视图,但是必须提供模型才能显示有用的信息。视图通过使用可以为每个视图单独维护或在多个视图之间共享的选择项来跟踪用户选择的项目。
有些视图,如QTableView和QTreeView,显示标题和项目。这些也由一个视图类QHeaderView实现。标题通常访问包含它们的视图的同一个模型。它们使用QAbstractItemModel::headerData()函数从模型中获取数据,并且通常以标签的形式显示标题信息。新的标题可以从QHeaderView类子类化,为视图提供更专门的标签。
使用已存在的视图
Qt提供了三个可用的视图类,它们以大多数用户熟悉的方式呈现模型中的数据。QListView可以将模型中的项目显示为简单的列表,或者以经典图标视图的形式显示。QTreeView将模型中的项目显示为列表的层次结构,允许以紧凑的方式表示深度嵌套结构。QTableView以表格的形式呈现模型中的项目,很像电子表格应用程序的布局。
上面显示的标准视图的默认行为应该足以满足大多数应用程序。它们提供基本的编辑功能,并可以进行定制以适应更专业的用户界面的需求。
使用模型
我们将创建的字符串列表模型作为示例模型,在其中设置一些数据,并构建一个视图来显示模型的内容。这些都可以在一个函数中完成:
int main(int argc, char *argv[])
{QApplication app(argc, argv);// Unindented for quoting purposes:QStringList numbers;numbers << "One" << "Two" << "Three" << "Four" << "Five";QAbstractItemModel *model = new StringListModel(numbers);
注意,StringListModel被声明为QAbstractItemModel。这允许我们使用模型的抽象接口,并确保代码仍然有效,即使我们将字符串列表模型替换为不同的模型。
QListView提供的列表视图足以显示string列表模型中的项目。我们使用下面的代码来构建视图和建立模型:
QListView *view = new QListView;
view->setModel(model);
视图按正常方式显示:
view->show();return app.exec();
}
视图渲染模型的内容,通过模型的接口访问数据。当用户试图编辑项时,视图使用默认委托来提供编辑器部件。
上图显示了QListView如何表示字符串列表模型中的数据。由于模型是可编辑的,视图自动允许使用默认委托编辑列表中的每一项。
使用模型的多个视图
为同一个模型提供多个视图,只需为每个视图设置相同的模型即可。在下面的代码中,我们创建了两个表视图,每个都使用了我们为这个例子创建的相同的简单表模型:
QTableView *firstTableView = new QTableView;QTableView *secondTableView = new QTableView;firstTableView->setModel(model);secondTableView->setModel(model);
在模型/视图架构中使用信号和槽意味着对模型的更改可以传播到所有附加的视图,确保我们始终可以访问相同的数据,无论使用的是哪个视图。
上图显示了同一个模型的两个不同视图,每个视图都包含一些选中的项目。尽管来自模型的数据在整个视图中一致地显示,但每个视图都维护自己的内部选择模型。这在某些情况下可能有用,但对于许多应用程序来说,共享选择模型是可取的。
选择模型
在视图中处理元素选择的机制由QItemSelectionModel类提供。所有的标准视图都默认构建自己的选择模型,并以正常的方式与它们交互。视图使用的选择模型可以通过selectionModel()函数获得,而替换选择模型可以通过setSelectionModel()指定。当我们想为同一个模型数据提供多个一致的视图时,控制视图使用的选择模型的能力很有用。
一般来说,除非是模型或视图的子类化,否则不需要直接操作选择的内容。不过,如果需要的话,选择模型的接口也是可以访问的,参考:处理Item视图中的选择。
视图间共享选择
虽然视图类默认提供自己的选择模型很方便,但当我们在同一个模型上使用多个视图时,通常希望模型的数据和用户的选择在所有视图中都保持一致。由于视图类允许替换它们的内部选择模型,我们可以使用以下代码实现视图之间的统一选择:
secondTableView->setSelectionModel(firstTableView->selectionModel());
第二个视图被赋予第一个视图的选择模型。现在,两个视图都在相同的选择模型上操作,保持数据和选择项同步。
在上面的示例中,使用两个相同类型的视图来显示相同模型的数据。但是,如果使用了两种不同类型的视图,则所选项目在每个视图中的表示可能非常不同;例如,表视图中的连续选择可以表示为树视图中突出显示的项目的碎片集。
处理Item视图中的选择
概念
item视图类中使用的选择模型提供了基于模型/视图体系结构的选择的一般描述。尽管操作选择的标准类对所提供的项目视图来说已经足够了,但是选择模型允许您创建专门的选择模型,以满足您自己的项目模型和视图的需求。
关于视图中所选项的信息存储在QItemSelectionModel类的一个实例中。它为单个模型中的项维护模型索引,并且独立于任何视图。由于一个模型可以有多个视图,因此可以在视图之间共享选择,从而允许应用程序以一致的方式显示多个视图。
选择由选择范围组成。这些方法通过仅记录每个选定项范围的起始和结束模型索引来有效地维护关于大量选择项的信息。通过使用多个选择范围来描述选择,构建非连续的选择项集;
选择应用于选择模型持有的模型索引集合。最近选择的应用项称为当前选择。这种选择的效果即使在应用后也可以通过使用某些类型的选择命令进行修改。本节稍后将讨论这些内容。
当前项目和已选项目
在视图中,总是有一个当前项和一个选定项——两个独立的状态。一个项目可以是当前项目,同时选择。视图负责确保始终有一个当前项,例如,键盘导航需要一个当前项。
下表突出显示了当前项和选定项之间的差异。
Current Item | Selected Items |
---|---|
当前项只能有一个。 | 可以有多个选择项。 |
当前项目将随着按键导航或鼠标按钮点击而改变。 | 当用户与项目交互时,项目的选择状态是被设置还是未设置,这取决于几种预定义的模式——例如,单选择、多选择等。 |
如果按下编辑键F2或双击项目,当前项目将被编辑(前提是启用编辑)。 | 当前元素可以和锚点一起使用,以指定选择或取消选择的范围(或两者的结合)。 |
当前项由焦点矩形表示。 | 选中的项目用选择矩形表示。 |
在操作选择时,通常可以将QItemSelectionModel视为一个项目模型中所有项目的选择状态的记录。一旦建立了选择模型,就可以选择、取消选择元素,或者切换它们的选择状态,而不需要知道哪些元素已经被选择了。所有选中项的索引可以随时被获取,并且可以通过信号和槽机制通知其他组件选择模型的变化。
使用选择模型
标准视图类提供了默认的选择模型,可以在大多数应用程序中使用。属于一个视图的选择模型可以使用视图的selectionModel()函数获得,并通过setSelectionModel()在多个视图之间共享,因此通常不需要构造新的选择模型。
通过指定一个模型和一对QItemSelection的模型索引来创建一个选择。这使用索引来引用给定模型中的项,并将它们解释为选定项块中的左上角和右下角项。要将选择应用于模型中的项目,需要将选择提交到选择模型;这可以通过多种方式实现,每种方式对选择模型中已经存在的选择有不同的影响。
选择项目
为了演示selection的一些主要特性,我们构建一个自定义表模型的实例,其中共有32个元素,然后打开一个表视图,查看其中的数据:
TableModel *model = new TableModel(8, 4, &app);QTableView *table = new QTableView(0);table->setModel(model);QItemSelectionModel *selectionModel = table->selectionModel();
表视图的默认选择模型会被检索出来以备以后使用。我们不修改模型中的任何项,而是选择一些将显示在表格左上角的项。为此,我们需要获取与待选择区域的左上角和右下角元素对应的模型索引:
QModelIndex topLeft;QModelIndex bottomRight;topLeft = model->index(0, 0, QModelIndex());bottomRight = model->index(5, 2, QModelIndex());
要在模型中选择这些项,并在tableview中查看相应的更改,需要构建一个selection对象,然后将其应用到selection模型中:
QItemSelection selection(topLeft, bottomRight);selectionModel->select(selection, QItemSelectionModel::Select);
使用由选择标志组合定义的命令,将选择应用于选择模型。在这种情况下,使用的标志会导致记录在selection对象中的项被包含在选择模型中,而不管它们之前的状态如何。结果选择显示在视图中。
通过选择标志定义的各种操作,可以修改对元素项的选择。这些操作产生的选择可能具有复杂的结构,但选择模型有效地表示了这些选择。在学习如何更新选区时,我们会介绍如何使用不同的选择标志来操作所选元素。
读取选区状态
可以使用selectedindex()函数读取存储在selection模型中的模型索引。这将返回一个未排序的模型索引列表,只要我们知道它们用于哪个模型,就可以对其进行迭代:
const QModelIndexList indexes = selectionModel->selectedIndexes();for (const QModelIndex &index : indexes) {QString text = QString("(%1,%2)").arg(index.row()).arg(index.column());model->setData(index, text);}
上面的代码使用基于范围的for循环来迭代和修改选择模型返回的索引对应的项。
选择模型发出信号来指示选择中的变化。它们通知其他组件关于整个选择和item模型中当前聚焦项的更改。我们可以将selectionChanged()信号连接到一个插槽,并在选择发生变化时检查模型中被选中或取消选中的项目。插槽用两个QItemSelection对象调用:一个包含一个索引列表,对应于新选择的项;另一个包含对应于新取消选择项的索引。
在下面的代码中,我们提供了一个槽,它接收selectionChanged()信号,用一个字符串填充选定的项目,并清除取消选择的项目的内容。
void MainWindow::updateSelection(const QItemSelection &selected,const QItemSelection &deselected)
{QModelIndexList items = selected.indexes();for (const QModelIndex &index : qAsConst(items)) {QString text = QString("(%1,%2)").arg(index.row()).arg(index.column());model->setData(index, text);}items = deselected.indexes();for (const QModelIndex &index : qAsConst(items)) {model->setData(index, QString());
}
我们可以通过将currentChanged()信号连接到一个插槽来跟踪当前聚焦的元素,该插槽通过两个模型索引调用。它们分别对应于前一个获得焦点的项和当前获得焦点的项。
在下面的代码中,我们提供了一个槽,它接收currentChanged()信号,并使用提供的信息更新QMainWindow的状态栏:
void MainWindow::changeCurrent(const QModelIndex ¤t,const QModelIndex &previous)
{statusBar()->showMessage(tr("Moved from (%1,%2) to (%3,%4)").arg(previous.row()).arg(previous.column()).arg(current.row()).arg(current.column()));
}
通过这些信号可以直接监控用户所做的选择,但我们也可以直接更新选择模型。
更新选区
选择命令由选择标志的组合提供,由QItemSelectionModel::SelectionFlag定义。每个选择标志都告诉选择模型,当调用任何一个select()函数时,如何更新选中项的内部记录。最常用的标志是Select标志,它指示选择模型将指定的项记录为已选择。切换标志使选择模型反转指定项的状态,即选择给定的任何未选择项,以及取消选择任何当前选中的项。Deselect标志用来取消选择所有指定的项目。
选择模型中的单个项目是通过创建一个项目选择并将其应用于选择模型来更新的。在下面的代码中,我们将第二次选择项应用到上面显示的表模型,使用Toggle命令翻转给定项的选择状态。
QItemSelection toggleSelection;topLeft = model->index(2, 1, QModelIndex());bottomRight = model->index(7, 3, QModelIndex());toggleSelection.select(topLeft, bottomRight);selectionModel->select(toggleSelection, QItemSelectionModel::Toggle);
操作的结果显示在table view中,提供了一种方便的可视化方式:
默认情况下,选择命令只对模型索引指定的单个项进行操作。但是,用于描述选择命令的标志可以与其他标志结合使用,以改变整个行和列。例如,如果调用select()时只有一个索引,但使用的命令是select和Rows的组合,那么包含引用的项的整行都会被选中。下列代码演示了如何使用Rows和Columns标志:
QItemSelection columnSelection;topLeft = model->index(0, 1, QModelIndex());bottomRight = model->index(0, 2, QModelIndex());columnSelection.select(topLeft, bottomRight);selectionModel->select(columnSelection,QItemSelectionModel::Select | QItemSelectionModel::Columns);QItemSelection rowSelection;topLeft = model->index(0, 0, QModelIndex());bottomRight = model->index(1, 0, QModelIndex());rowSelection.select(topLeft, bottomRight);selectionModel->select(rowSelection,QItemSelectionModel::Select | QItemSelectionModel::Rows);
虽然只向选择模型提供了4个索引,但使用行和列选择标志意味着选择了两列和两行。下图显示了这两种选择的结果:
在示例模型上执行的命令都涉及对模型中选择的项目进行累积。也可以清除选区,或者用一个新的选区替换当前选区。
要将当前选区替换为新的选区,需要将其他选区标志与当前标志合并。使用此标志的命令指示选择模型用调用select()时指定的索引替换当前的模型索引集合。要在开始添加新选择之前清除所有选择,请将其他选择标志与clear标志结合起来。这具有重置选择模型的模型索引集合的效果。
选择模型中的所有项
为了选择模型中的所有项,需要为模型的每一层创建一个覆盖该层中所有项的选择。为此,可以使用给定的父索引检索左上角和右下角元素对应的索引:
QModelIndex topLeft = model->index(0, 0, parent);QModelIndex bottomRight = model->index(model->rowCount(parent)-1,model->columnCount(parent)-1, parent);
利用这些指标和模型进行选择。然后在selection模型中选择相应的项:
QItemSelection selection(topLeft, bottomRight);selectionModel->select(selection, QItemSelectionModel::Select);
这需要对模型中的所有级别执行。对于顶级元素,我们将按照通常的方式定义父索引:
QModelIndex parent = QModelIndex();
对于分层模型,hasChildren()函数用于确定任何给定项是否为另一层项的父项。
Model/View Programming | Qt Widgets 5.15.17
相关文章:

QT Mode/View之View
目录 概念 使用已存在的视图 使用模型 使用模型的多个视图 处理元素的选择 视图间共享选择 概念 在模型/视图架构中,视图从模型中获取数据项并将它们呈现给用户。数据的表示方式不必与模型提供的数据表示形式相似,而且可能与用于存储数据项的底层数…...

URP 线性空间 ui资源制作规范
前言: 关于颜色空间的介绍,可参阅 unity 文档 Color space URP实现了基于物理的渲染,为了保证光照计算的准确,需要使用线性空间; 使用线性空间会带来一个问题,ui资源在unity中进行透明度混合时ÿ…...

如何精确统计Pytorch模型推理时间
文章目录 0 背景1 精确统计方法2 手动synchronize和Event适用场景 0 背景 在分析模型性能时需要精确地统计出模型的推理时间,但仅仅通过在模型推理前后打时间戳然后相减得到的时间其实是Host侧向Device侧下发指令的时间。如下图所示,Host侧下发指令与De…...

Mybatis-plus-Generator 3.5.5 自定义模板支持 (DTO/VO 等) 配置
随着项目节奏越来越快,为了减少把时间浪费在新建DTO 、VO 等地方,直接直接基于Mybatis-plus 这颗大树稍微扩展一下,在原来生成PO、 DAO、Service、ServiceImpl、Controller 基础新增。为了解决这个问题,网上找了一堆资料ÿ…...
C#环境下MAC地址获取方法解析
在C#中,获取MAC地址并不是直接支持的,因为出于安全和隐私的考虑,操作系统通常会限制对这类硬件信息的直接访问。不过,仍然可以通过一些方法间接地获取到本地网络接口(比如以太网接口)的MAC地址。 以下是几…...
(k8s)Kubernetes 从0到1容器编排之旅
一、引言 在当今数字化的浪潮中,Kubernetes 如同一艘强大的航船,引领着容器化应用的部署与管理。它以其卓越的灵活性、可扩展性和可靠性,成为众多企业和开发者的首选。然而,要真正发挥 Kubernetes 的强大威力,仅仅掌握…...
Rust Web开发框架对比:Warp与Actix-web
文章目录 Rust Web开发框架对比:Warp与Actix-web引言框架概述Warp框架简介Actix-web框架简介 设计理念Warp的设计理念Actix-web的设计理念 性能比较可扩展性和生态插件和中间件支持社区和文档 使用示例使用Warp构建简单的HTTP服务使用Actix-web构建简单的HTTP服务 学…...

F12抓包12:Performance(性能)前端性能分析
课程大纲 使用场景: ① 前端界面加载性能测试。 ② 导出性能报告给前端开发。 复习:后端(接口)性能分析 ① 所有请求耗时时间轴:“网络”(Network) - 概览。 ② 单个请求耗时:“网络”(Network…...

数据结构(Day13)
一、学习内容 内存空间划分 1、一个进程启动后,计算机会给该进程分配4G的虚拟内存 2、其中0G-3G是用户空间【程序员写代码操作部分】【应用层】 3、3G-4G是内核空间【与底层驱动有关】 4、所有进程共享3G-4G的内核空间,每个进程独立拥有0G-3G的用户空间 …...

链表的快速排序(C/C++实现)
一、前言 大家在做需要排名的项目的时候,需要把各种数据从高到低排序。如果用的快速排序的话,处理数组是十分简单的。因为数组的存储空间的连续的,可以通过下标就可以简单的实现。但如果是链表的话,内存地址是随机分配的…...
css总结(记录一下...)
文字 语法说明word-wrapword-wrap:normal| break-word normal:使用浏览器默认的换行 break-word:允许在单词内换行 text-overflow clip:修剪文本 ellipsis:显示省略符号来代表被修剪的文本 text-shadow可向文本应用的阴影。能够规定水平阴影、垂直阴影、模糊距离,以…...

SpringBoot 处理 @KafkaListener 消息
消息监听容器 1、KafkaMessageListenerContainer 由spring提供用于监听以及拉取消息,并将这些消息按指定格式转换后交给由KafkaListener注解的方法处理,相当于一个消费者; 看看其整体代码结构: 可以发现其入口方法为doStart(),…...
Spring Boot-API版本控制问题
在现代软件开发中,API(应用程序接口)版本控制是一项至关重要的技术。随着应用的不断迭代,API 的改动不可避免,如何在引入新版本的同时保证向后兼容,避免对现有用户的影响,是每个开发者需要考虑的…...
Git 提取和拉取的区别在哪
1. 提取(Fetch) 操作说明:Fetch 操作会从远程仓库下载最新的提交、分支信息等,但不会将这些更改合并到你当前的分支中。它只是将远程仓库的更新信息存储在本地,并不会自动修改你当前的工作区。 使用场景: …...
【数据结构与算法 | 每日一题 | 力扣篇】力扣2390, 2848
1. 力扣2390:从字符串中删除星号 1.1 题目: 给你一个包含若干星号 * 的字符串 s 。 在一步操作中,你可以: 选中 s 中的一个星号。移除星号 左侧 最近的那个 非星号 字符,并移除该星号自身。 返回移除 所有 星号之…...

破解信息架构实施的密码:常见挑战与最佳解决方案全指南
信息架构的成功实施是企业数字化转型的关键步骤,但在实际操作中,企业往往会遇到各种复杂的挑战。这些挑战包括 技术整合的难度、数据管理的复杂性、合规性要求的变化 以及 资源限制 等。《信息架构:商业智能&分析与元数据管理参考模型》为…...
CodeChef Starters 151 (Div.2) A~D
codechef是真敢给分,上把刚注册,这把就div2了,再加上一周没打过还是有点不适应的,好在最后还是能够顺利上分 今天的封面是P3R的设置菜单 我抠出来做我自己的游戏主页了( A - Convert string 题意 在01串里面可以翻转…...

Redis学习——数据不一致怎么办?更新缓存失败了又怎么办?
文章目录 引言正文读写缓存的数据一致性只读缓存的数据一致性删除和修改数据不一致问题操作执行失败导致数据不一致解决办法 多线程访问导致数据不一致问题总结 总结参考信息 引言 最近面试快手的时候被问到了缓存不一致怎么解决?一开始还是很懵的,因为…...

跨境电商代购新纪元:一键解锁全球好物,系统流程全揭秘
添加图片注释,不超过 140 字(可选) 在全球化日益加深的今天,跨境电商代购成为了连接消费者与世界各地优质商品的桥梁。本文将在CSDN平台上,深入剖析跨境电商代购系统的功能流程,带您一窥其背后的技术奥秘与…...

Mac 上终端使用 MySql 记录
文章目录 下载安装终端进入 MySql常用操作查看数据库选择一个数据库查看当前选择的数据库Navcat 打开提示报错参考文章 下载安装 先下载社区版的 MySql 安装的过程需要设置 root 的密码,这个是要进入数据库所设定的,所以要记住 终端进入 MySql 首先输…...
Android Wi-Fi 连接失败日志分析
1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分: 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析: CTR…...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...
【Java学习笔记】Arrays类
Arrays 类 1. 导入包:import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序(自然排序和定制排序)Arrays.binarySearch()通过二分搜索法进行查找(前提:数组是…...

12.找到字符串中所有字母异位词
🧠 题目解析 题目描述: 给定两个字符串 s 和 p,找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义: 若两个字符串包含的字符种类和出现次数完全相同,顺序无所谓,则互为…...

VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP
编辑-虚拟网络编辑器-更改设置 选择桥接模式,然后找到相应的网卡(可以查看自己本机的网络连接) windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置,选择刚才配置的桥接模式 静态ip设置: 我用的ubuntu24桌…...

Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战
说明:这是一个机器学习实战项目(附带数据代码文档),如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下,风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...

【Linux系统】Linux环境变量:系统配置的隐形指挥官
。# Linux系列 文章目录 前言一、环境变量的概念二、常见的环境变量三、环境变量特点及其相关指令3.1 环境变量的全局性3.2、环境变量的生命周期 四、环境变量的组织方式五、C语言对环境变量的操作5.1 设置环境变量:setenv5.2 删除环境变量:unsetenv5.3 遍历所有环境…...

论文阅读笔记——Muffin: Testing Deep Learning Libraries via Neural Architecture Fuzzing
Muffin 论文 现有方法 CRADLE 和 LEMON,依赖模型推理阶段输出进行差分测试,但在训练阶段是不可行的,因为训练阶段直到最后才有固定输出,中间过程是不断变化的。API 库覆盖低,因为各个 API 都是在各种具体场景下使用。…...

uniapp 小程序 学习(一)
利用Hbuilder 创建项目 运行到内置浏览器看效果 下载微信小程序 安装到Hbuilder 下载地址 :开发者工具默认安装 设置服务端口号 在Hbuilder中设置微信小程序 配置 找到运行设置,将微信开发者工具放入到Hbuilder中, 打开后出现 如下 bug 解…...

tauri项目,如何在rust端读取电脑环境变量
如果想在前端通过调用来获取环境变量的值,可以通过标准的依赖: std::env::var(name).ok() 想在前端通过调用来获取,可以写一个command函数: #[tauri::command] pub fn get_env_var(name: String) -> Result<String, Stri…...