前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Qt Model/View教程——只读Table

Qt Model/View教程——只读Table

作者头像
用户5908113
发布2020-02-12 16:11:08
1.9K0
发布2020-02-12 16:11:08
举报
文章被收录于专栏:Pou光明Pou光明

一直想学习Qt Model/View,最终还是看的官方教程,现在将官方教程重新在梳理下。

每个UI开发人员都应该了解Model/View编程!可见Model/View在UI编程中的重要性!

那它为什么这么重要呢?

Table,、List和Tree widgets是GUI中经常使用的组件。 这些小部件可以通过两种不同的方式访问其数据。 传统方式部件使用内部容器进行存储数据。,这种方法非常直观,但是,在许多特别的应用程序中,它会导致数据同步问题。 第二种方法是模型/视图编程,其中小部件不维护内部数据容器。 他们通过标准化接口访问外部数据,因此避免了数据重复。 乍一看,这似乎很复杂,但是一旦仔细研究,不仅容易掌握,而且模型/视图编程的许多好处也变得更加清晰。

整个教程的目录如下:

标准部件和模型/视图部件之间的区别

表单和模型之间的适配器

开发一个简单的模型/视图应用程序

预定义模型

中级主题:

Tree views

Selection

Delegates

Debugging with model test

一、 概述

模型/视图是一种用于将数据与处理数据集的小部件中的视图分离的技术。 标准窗口小部件并非旨在将数据与视图分离,这就是为什么Qt具有两种不同类型的窗口小部件的原因。 两种类型的小部件外观相同,但是它们与数据的交互方式不同。

1. 标准部件

Table Widget是用户可以更改的数据元素的2D部件。 可以通过读写表小部件提供的数据元素将表小部件集成到程序中。 此方法非常直观,在许多应用程序中很有用,但是使用标准表窗口部件显示和编辑数据库表可能会出现问题。 数据的两个副本必须协调一致:一个在小部件外部;另一个在小部件内部。 开发人员必须负责同步两个数据副本。 除此之外,数据的紧密耦合使编写单元测试更加困难。

2. Model/View

Model/View使用了更加灵活的体系结构来提供解决方案。Model/View消除了标准小部件可能发生的数据一致性问题, 而且Model/View还可以让同一数据源在多个视图上进行显示变得更加方便;因为一个Model可以传递给许多Views。 最重要的区别是Model/View部件不在表单内部存储数据。 实际上,Model/View直接对您的数据进行操作。 由于视图类不知道数据的结构,因此需要提供包装器以使数据符合QAbstractItemModel接口【译者注:这就是为什么要setMode】。 View使用该接口进行读取和写入数据,实现QAbstractItemModel的类的任何实例都称为模型【译者注:什么是Model】。 一旦View接收到指向模型的指针,它将读取并显示其内容并成为其编辑器【译者注:setModel后,View自动读取数据并显示】。

二、 一个简单的Model/View应用程序

如果要开发Model/View应用程序,应该从哪里开始? 我们建议从一个简单的示例开始【译者注:我表示非常赞同!】,并逐步扩展它,这使得了解架构变得容易得多。 事实证明,在调用集成好的接口前尝试详细了解Model/View体系结构对于许多开发人员来说并不方便。 从具有演示数据的简单Model/View应用程序开始要容易得多。 试试看! 只需将以下示例中的数据替换为您自己的数据即可。

以下是7个非常简单和独立的应用程序,它们展示了模型/视图编程的不同方面。 可以在examples/widgets/tutorials/modelview目录中找到源代码。

1. 只读Table

我们从使用QTableView来显示数据的应用程序开始。之后我们将添加编辑功能。

只读table,效果如下:

我们创建MyModel的实例并使用tableView.setModel(&myModel), 将其指针传递给tableView ,tableView将调用它收到的指针获得以下信息:

应显示多少行和多少列

每个单元格应显示什么内容

Model需要一些代码来对此做出响应。我们有一个表数据集,因此让我们从QAbstractTableModel开始,因为它比更通用的QAbstractItemModel更加易于使用。【译者注:以后会更加了解这两个类的】

mymodel.h 代码:

代码语言:javascript
复制
#include <QAbstractTableModel>

class MyModel : public QAbstractTableModel
{
    Q_OBJECT
public:
    MyModel(QObject *parent);
    int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE ;
    int columnCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE;
};

QAbstractTableModel需要实现三种抽象方法。

mymodel.cpp 代码:

代码语言:javascript
复制
#include "mymodel.h"

MyModel::MyModel(QObject *parent)
    :QAbstractTableModel(parent)
{
}

int MyModel::rowCount(const QModelIndex & /*parent*/) const
{
   return 2;
}

int MyModel::columnCount(const QModelIndex & /*parent*/) const
{
    return 3;
}

QVariant MyModel::data(const QModelIndex &index, int role) const
{
    if (role == Qt::DisplayRole)
    {
       return QString("Row%1, Column%2")
                   .arg(index.row() + 1)
                   .arg(index.column() +1);
    }
    return QVariant();
}

行数和列数由MyModel :: rowCount()和MyModel :: columnCount()提供 。 当视图必须知道单元格的文本是什么时,它将调用方法MyModel :: data() 。 行和列信息由参数index指定,并且角色设置为Qt :: DisplayRole 。 下一节将介绍其他角色。 在我们的示例中,应显示的数据已生成。 在实际的应用程序中, MyModel会有一个名为MyData的成员,该成员充当所有读取和写入操作的目标。

这个小例子说明了模型的被动性质。 该模型不知道何时使用它或需要哪些数据。 每次视图请求时,它仅提供数据。

当需要更改模型数据时会发生什么? 视图如何认识到数据已更改并且需要再次读取? 该模型必须发出一个信号,该信号指示已更改了哪些单元格范围。 这将在第2.3节中演示。

总结:

之前由于项目需要,使用过Qt的文件系统模型,当时直接用的现成的程序,那会儿就很不明白为什么一定要setModel,设置完后又会自己显示。教程看到这之后,终于明白了。所以我比较喜欢知道为什么这么做、这么做应该会有一个什么样的结果。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-01-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Pou光明 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档