Qt MV架构-视图类

news2024/9/22 5:27:04

一、基本概念

在MV架构中,视图包含了模型中的数据项,并将它们呈现给用户。数据项的表示方法,可能和数据项在存储时用的数据结构完全不同。

这种内容与表现分离之所以能够实现,是因为使用了

  1. QAbstractItemModel提供的一个标准模型接口;
  2. 一个标准视图接口;
  3. 模型索引所提供的一种通用的方法;

来表示数据。

视图通常管理从模型获取数据的整体布局。视图可以自己渲染独立的数据项,也可以使用委托来处理渲染和编辑。

1. 项目导航和选择行为

除了呈现数据,视图还处理项目间的导航,以及项目选择的某些方面。
表1和表2分别罗列了视图中的选择行为(QAbstractItemView::SelectionBehaviour)和选择模式(QAbstractItemView::SelectionMode

表1 视图类的选择行为(QAbstractItemView::SelectionBehaviour)

常量描述
QAbstractItemView::SelectItems选择单个项目
QAbstractItemView::SelectRows只选择行
QAbstractItemView::SelectColumns只选择列

表2 视图类的选择模式

常量描述
QAbstractItemView::SingleSelection当用户选择一个项目,索所有已选择的项目将成为未选择态,而且用户无法在已经选择的项目上单击来取消选择。
QAbstractItemView::ContiguousSelection如果用户在单击一个项目的同时按着Shift键,所有在当前和单击项目之间的项目都将被选择或者取消选择,这依赖于被单击项目的状态。
QAbstractItemView::ExtendedSelection具有ConiguousSelection的特性,而且还可以按着Ctrl键进行不连续的选择。
QAbstractItemView::MultiSelection用户选择一个项目时,不影响其他已经选择的项目。
QAbstractItemView::NoSelection项目无法被选择。

对于一些视图,例如QTreeViewQTreeView,在显示项目的同时还可以显示表头。这是通过QHeaderView类来实现的,它们使用QAbstractItemModel::headerData()从模型中获取数据,然后一般使用一个标签来显示表头信息。可以通过子类化QHeaderView来设置标签的显示。

Qt中已经提供了QListView,QTableViewQTreeView这三个现成的视图,不过都是使用规范的格式显示数据。
如果想要实现条形图、饼状图等特殊显示方式,需要重新实现视图。

二、项目选择

MV架构对项目的选择提供了非常方便的处理方法。
视图中被选择的项目的信息,存储在一个QItemSelectionModel实例中,这样被选择的项目模型索引便保持在一个独立的模型中,与所有的视图都是独立的。

当在一个模型上设置多个视图时,就可以实现在多个视图之间共享选择

选择由选择范围指定,只需要记录每一个选择范围开始和结束的模型索引即可,非连续的选择可以使用多个选择范围来描述。
选择可以看作是在选择模型中保存的一个模型索引集合,最近的项目选择被称为当前选择。

1. 当前项目、被选择项目

视图中总是有一个当前项目和一个被选择的项目,两者是独立的状态。

在同一时间,一个项目可以既是当前项目,同时也是被选择项目。视图负责确保总是有一个项目作为当前项目来实现键盘导航。

表3 当前项目和被选择的项目的区别

当前项目被选择的项目
只能有一个当前项目被选择的项目
使用键盘导航键或者鼠标按键可以改变当前项目项目是否处于被选择状态,取决于几个预先定义好的模式,例如单项选择、多重选择等。
如果按下F2键或者双击都可以编辑当前项目当前项目可以通过指定一个范围来一起被使用
当前项目会显示焦点矩形被选择的项目会使用选择矩形来表示

当操作选择时,可以将QItemnSelectionModel看作一个项目模型中所有项目的选择状态的一个记录。
一旦设置了一个选择模型,所有的项目集合都可以被选择、取消选择或者切换选择状态,而不需要知道哪一个项目已经被选择了。所有被选择项目的索引都可以被随时进行检索,其他的组件也可以通过信号和槽机制来获取选择模型的改变信息。

2. 选择模型

标准的视图类中提供了默认的选择模型,可以在大多数的应用中直接使用。
属于一个视图的选择模型可以使用这个视图的selectionModel()函数获得,而且还可以在多个视图之间使用setSelectionModel()函数来共享该选择模型,所以一般是不需要重新构建一个选择模型的。

三、代码实例

实现两个视图共享数据模型和选择模型。

在这里插入图片描述
MainWindow.h

#pragma once

#include <QMainWindow>

class QTableView;
class QItemSelection;
class QModelIndex;

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow {
Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow() override;
public slots:
	void getCurrentItemData();
	void toggleSelection();
	void updateSelection(const QItemSelection &selected, const QItemSelection &deselected);
	void changeCurrent(const QModelIndex &current, const QModelIndex &previous);
private:
    Ui::MainWindow *ui;
	QTableView* tableView;
	QTableView* tableView2;
};

MainWindow.cpp

#include "mainwindow.h"
#include "ui_MainWindow.h"
#include <QStandardItemModel>
#include <QTableView>
#include <QDebug>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent), ui(new Ui::MainWindow) {
    ui->setupUi(this);

    auto model = new QStandardItemModel(7, 4, this);
    for (int row = 0; row < 7; ++row) {
	    for (int column = 0; column < 4; ++column) {
		    auto item = new QStandardItem(QString("%1").arg(row * 4 + column));
		    model->setItem(row, column, item);
	    }
    }

    tableView = new QTableView;
    tableView->setModel(model);
    setCentralWidget(tableView);

	QItemSelectionModel* selectionModel = tableView->selectionModel();

	QModelIndex topLeft;
	QModelIndex bottomRight;
	topLeft = model->index(1,1,QModelIndex());
	bottomRight = model->index(5,2,QModelIndex());
	QItemSelection selection(topLeft, bottomRight);
	selectionModel->select(selection, QItemSelectionModel::Toggle);

    ui->menubar->addAction(tr("当前项目"), this, &MainWindow::getCurrentItemData);
    ui->menubar->addAction(tr("切换选择"), this, &MainWindow::toggleSelection);

	connect(selectionModel, &QItemSelectionModel::selectionChanged,this, &MainWindow::updateSelection);
	connect(selectionModel, &QItemSelectionModel::currentChanged,this,&MainWindow::changeCurrent);
    {
	    tableView2 = new QTableView;
    	tableView2->setWindowTitle("tableView2");
    	tableView2->resize(400,300);
    	tableView2->setModel(tableView->model());
    	tableView2->setSelectionModel(tableView->selectionModel());
    	tableView2->show();
    }
}

MainWindow::~MainWindow() {
    delete ui;
	delete tableView2;
}

void
MainWindow::getCurrentItemData()
{
	qDebug() << tr("当前项目内容")
	<< tableView->selectionModel()->currentIndex().data().toString();
}

void
MainWindow::toggleSelection()
{
	QModelIndex topLeft     = tableView->model()->index(0,0,QModelIndex());
	QModelIndex bottomRight = tableView->model()->index(
		tableView->model()->rowCount(QModelIndex()) - 1,
		tableView->model()->columnCount(QModelIndex()) - 1,
		QModelIndex());
	QItemSelection curSelection(topLeft, bottomRight);
	tableView->selectionModel()->select(curSelection, QItemSelectionModel::Toggle);
}

void
MainWindow::updateSelection(const QItemSelection &selected, const QItemSelection &deselected)
{
	QModelIndex index;
	QModelIndexList list = selected.indexes();
	foreach(index, list)
	{
		QString text = QString("%1,%2").arg(index.row()).arg(index.column());
		tableView->model()->setData(index, text);
	}
	list = deselected.indexes();

	foreach(index, list)
	{
		tableView->model()->setData(index, "");
	}
}

void
MainWindow::changeCurrent(const QModelIndex &current, const QModelIndex &previous)
{
	qDebug() << tr("move(%1,%2) to (%3,%4)").
	arg(previous.row()).arg(previous.column()).
	arg(current.row()).arg(current.column());
}

参考资料: Qt Creator快速入门第2版 (霍亚飞 著)

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

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

相关文章

Go语言---TCP服务端以及客服端的实现

TCP的C/S架构 TCP服务器的实现 监听的底层实现 func Listen(network, address string) (Listener, error) {var lc ListenConfigreturn lc.Listen(context.Background(), network, address) }type Listener interface {// Accept waits for and returns the next connection …

Jenkins中Node节点与构建任务

目录 节点在 Jenkins 中的主要作用 1. 分布式构建 分布式处理 负载均衡 2. 提供不同的运行环境 多平台支持 特殊环境需求 3. 提高资源利用率 动态资源管理 云端集成 4. 提供隔离和安全性 任务隔离 权限控制 5. 提高可扩展性 横向扩展 高可用性 Jenkins 主服务…

【深度学习入门篇 ⑤ 】PyTorch网络模型创建

【&#x1f34a;易编橙&#xff1a;一个帮助编程小伙伴少走弯路的终身成长社群&#x1f34a;】 大家好&#xff0c;我是小森( &#xfe61;ˆoˆ&#xfe61; ) &#xff01; 易编橙终身成长社群创始团队嘉宾&#xff0c;橙似锦计划领衔成员、阿里云专家博主、腾讯云内容共创官…

注册中心与配置中心,是分?是合?

一零年代初&#xff0c;我还自己动手写过socket连接来做服务注册发现&#xff0c;后来有了zookeeper就方便多了&#xff0c;那时候zookeeper也直接做配置中心使用。后来出现了一些专门的服务注册发现组件如Eureka\etcd\consul&#xff0c;专门的配置中心比如spring cloud confi…

2024年上半年信息系统项目管理师——综合知识真题题目及答案(第1批次)(2)

2024年上半年信息系统项目管理师 ——综合知识真题题目及答案&#xff08;第1批次&#xff09;&#xff08;2&#xff09; 第21题&#xff1a;在一个大型信息系统项目中&#xff0c;项目经理发现尽管已经建立了沟通机制&#xff0c;但团队间的沟通依然不畅&#xff0c;项目风险…

【JavaScript】解决 JavaScript 语言报错:Uncaught SyntaxError: Unexpected token

文章目录 一、背景介绍常见场景 二、报错信息解析三、常见原因分析1. 缺少必要的语法元素2. 使用了不正确的字符或符号3. JSON 格式错误4. 字符串未正确闭合 四、解决方案与预防措施1. 检查语法元素2. 正确使用符号和字符3. 修正 JSON 格式4. 字符串闭合 五、示例代码和实践建议…

C++基础语法:STL之迭代器

前言 "打牢基础,万事不愁" .C的基础语法的学习 引入 C基础:STL概述-CSDN博客 上一篇梳理了一些同STL有关的概念.同时对理解迭代器需要的类包含,内部类,链表等内容做了分析,这篇从<C Prime Plus> 6th Edition(以下称"本书")的P684,大标题16.4泛型编…

Sortable.js板块拖拽示例

图例 代码在图片后面 点赞❤️关注&#x1f64f;收藏⭐️ 页面加载后显示 拖拽效果 源代码 由于js库使用外链&#xff0c;所以会加载一会儿 <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <meta name&qu…

Pycharm 导入 conda 环境

使用时经常在此处卡壳&#xff0c;在此做个记录。 这个位置选择 conda 安装路径下的 python.exe 文件即可

书生浦语大模型实战营---Linux 基础知识

创建开发机 开建开发机首先填写开发机名称&#xff0c;选择镜像和配置资源&#xff0c;最后选择立即创建 ssh免密钥登陆 1、本地执行ssh-keygen -t rsa&#xff0c;然后一路回车就可以了 2、执行cat ~/.ssh/id_rsa.pub 3、回到开发机平台&#xff0c;在首页点击配置SSH Key…

手机数据恢复篇:如何从 Android 设备内恢复数据

如何从 Android 内部存储恢复数据&#xff1f; 要从 Android 内部存储恢复已删除的文件&#xff0c;您需要一个 Android 内部存储恢复应用或程序。请继续阅读以获取可靠的 Android 数据恢复软件&#xff0c;并让它帮助您从 Android 手机的内部存储恢复数据。 是否有可能恢复 An…

工业大数据是什么?应用工业大数据时面临哪些挑战?

在当今快速发展的工业领域&#xff0c;大数据已成为推动企业转型升级的核心动力。工业大数据&#xff0c;以其独特的价值和潜力&#xff0c;正逐渐改变着传统的生产、管理和决策模式。然而&#xff0c;伴随着大数据的快速发展&#xff0c;一系列挑战也随之浮现。本文将深入探讨…

刷题之单词规律同构字符串(leetcode)

同构字符串 单词规律 两个都是映射关系&#xff0c;用两张哈希表记录互相映射就可以了 同构字符串&#xff1a; class Solution { public:bool isIsomorphic(string s, string t) {//用两张哈希表做映射if(s.size()!t.size()){return false;}unordered_map<char,char&…

零基础学JS之APIS

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 非常期待和您一起在这个小…

算法day04 位运算 插入排序 二分法 对数器

位运算: 1&#xff09;有一个数组只包含这样的数&#xff0c;有几个数出现偶数次&#xff0c;有1个数出现奇数次&#xff0c;要求时间复杂度不超过o(n),怎么求出现奇数次的数。 使用 ^ 异或运算整个数组&#xff0c;偶数次运算结果为0&#xff0c;只留下最后一个奇数次的数。 …

【零基础】学JS之APIS第四天

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 非常期待和您一起在这个小…

网络层重点协议—IP协议

在复杂的网络环境中确定一个合适的路径 协议头格式如下&#xff1a; 4位版本号(version) 指定协议的版本&#xff08;IPV4-4,IPV6-6&#xff09; 4位首部长度(header length) IP头部的长度是多少个32bit&#xff0c;也就是length*4的字节数。4bit表示最大的数字是15&#x…

记一次TIDB开启TLS失败导致PD扩容失败案例

作者&#xff1a; Dora 原文来源&#xff1a; https://tidb.net/blog/8ee8f295 问题背景 集群之前由于TIUP目录被删除导致TLLS证书丢失&#xff0c;后续需要重新开启TLS 在测试环境测试TLS开启步骤&#xff0c;导致后续两台PD扩容失败&#xff0c;步骤如下&#xff1a; …

Linux Win 10 Windows上安装Ollama部署大模型qwen2 7b/15配置启动 LangChain-ChatChat 0.2.10进行对话

Win 10 Window安装Ollama部署qwen2 7b LangChain-ChatChat 环境说明 Win 10 Python 3.11.9 LangChain-ChatChat 0.20 Ollama 0.2.10 Qwen2 1.5b/7b Windows 安装Ollama 下载并安装Windows版Ollama https://ollama.com/download#/ 下载大模型qwen2:1.5b或者qwen2:7b 在命令…

电子技术员基础

这是介绍电子技术员必须掌握的基础知识&#xff0c;在维修和测试中可能有所帮助。放在电脑里有几十年了&#xff0c;是我早期在做电子技术员期间做的文档&#xff0c;所有插图都是自己做的&#xff0c;当初学习态度是绝对认真。如果把这股子劲用在考研上呢&#xff0c;... ...&…