Qt Model/View教程——只读Table

点击上方蓝字可直接关注!方便下次阅读。如果对你有帮助,可以点个在看,让它可以帮助到更多老铁~
一直想学习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 代码:

#include 


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 代码:

#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,体验全力做一件事的幸福与艰辛!
欢迎关注公众号: