MVC模型/视图编程

Qt中的模型/视图架构用来实现大量的数据存储、处理及显示。

MVC(Model-View-Controller)包括了3个组件:

  • 模型(Model)是应用对象,用来表示数据;
  • 视图(View)是模型的用户界面,用来显示数据;
  • 控制(Controller)定义了用户界面对用户输入的反应方式。委托(Delegate)用于定制数据的渲染和编辑方式。

1. 模型

  • 所有的模型都基于QAbstractItemModel类,该类提供了十分灵活的接口来处理各种视图,这些视图可以将数据的表现形式为表格(table)、列表(list)、树(tree)

  • Qt提供了一些现成的模型来处理数据项:

  • QStringListModel 存储简单的QString项目列表;

  • QStandardItemModel管理复杂的属性结构数据项,每一个数据项可以包含任意的数据;

  • QFileSystemModel提供了本地文件系统中文件和目录信息;

  • QSqlQueryModel、QSqlTableModel和QSqlRelationTableModel用来访问数据库。

  • 标准模型还无法满足需要时,可子类化QAbstractItemModel、QAbstractListModel或QAbstractTableModel来创建自定义的模型。

常见的3种模型为列表模型、表格模型、树模型,如下图所示:

模型索引

  • 为确保数据的表示与数据的获取相分离,Qt引入了模型索引的概念,输入和委托均可通过模型索引来请求数据并显示。只有模型需要知道怎样获取数据,被模型管理的数据类型可以被广泛的定义。模型索引包含一个指针,指向创建他们的模型,使用多个模型时可避免混淆。模型索引QModelIndex类提供对一块数据的临时引用,用来修改或检索模型中的数据,获取一个数据项的模型索引必须指定模型的3个属性:行号、列号和父项的模型索引。
  • 如:QModelIndex index = model->index(row,column,parent);
  • 也可通过模型指定的相关数据项对应的模型索引以及特定的角色来获取需要的类型数据,
  • 如:QVariant value = model->data(index,role);
    常用的角色类型:
常量 描述
Qt::DisplayRole 数据被渲染为文本(数据为QString类型)
Qt::DecorationRole 数据被渲染为图标等装饰(数据为QColor,QIcon,或QPixmap类型)
Qt::EditRole 数据可以在编辑器中进行编辑(数据为QString类型)
Qt::ToolTipRole 数据显示在数据项的工具提示中(数据类型为QString)
Qt::StatusTipRole 数据显示在状态栏中(数据为QString类型)
Qt::WhatsThisRole 数据显示在数据项的“What’s This?”模式下(数据为QString类型)
Qt::SizeHintRole 数据项的大小提示,将会应用到视图(数据为QSize类型)
Qt::FontRole 默认代理的绘制使用的字体
Qt::TextAlignmentRole 默认代理的对齐方式
Qt::BackgroundRole 默认代理的背景画刷
Qt::ForegroundRole 默认代理的前景画刷
Qt::CheckStateRole 默认代理的检查框状态
Qt::UserRole 用户自定义的数据的起始位置
  • 新建名称testModelIndex, 选择空项目, 工程文件中添加 QT += widgets
  • 添加main.cpp文件

2.视图

  • Qt提供了QListView、QTableView视图、QTreeView视图分别实现列表、表格与树视图效果。
  • QListView将数据项显示为一个列表;
  • QTableView将模型中的数据显示在一个表格中;
  • QTreeView将模型中的数据项显示在具有层次的列表中。
  • QTableView和QTreeView在显示项目的时候同时还可以显示标头,通过QHeaderView类实现。
  • 自定义视图类是基于QAbstractItemView抽象基类,如实现条形图,饼状图等特殊显示方式。

视图类的选择行为

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

视图类的选择模式

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

选择模型更新方式

常量 描述
QItemSelectionModel::NoUpdate 不做选择
QItemSelectionModel::Clear 选择被清除
QItemSelectionModel::Select 选择指定索引
QItemSelectionModel::Deselect 取消指定索引的选择
QItemSelectionModel::Toggle 切换指定索引的选择
QItemSelectionModel::Current 当前选择被更新
QItemSelectionModel::Rows 索引扩展为跨行
QItemSelectionModel::Columns 索引扩展为跨列
QItemSelectionModel::SelectCurrent Select Current组合
QItemSelectionModel::ToggleCurrent Toggle Current组合
QItemSelectionModel::ClearAndSelect Clear Select组合

3. 委托

  • 在模型/视图框架中,QAbstractItemDelegate是委托类的抽象基类,Qt默认的委托实现由QStyledItemDelegate类提供,这也被用作Qt标准视图的默认委托,选择 QStyledItemDelegate或QItemDelegate中其一来为视图中的项目绘制和提供编辑器。
  • 不同的是QStyledItemDelegate使用当前的样式来绘制项目,实现自定义委托建议使用QStyledItemDelegate作为基类。
  • Qt提供了项目试图的便捷类,这些类底层通过模型/视图框架实现。这些部件分别是QListWidget提供一个项目列表,QTreeWidget显示一个多层次的树结构,QTableWidget提供了一个以项目作为单元的表格。它们每一个类都继承了QAbstractItemView类的行为。之所以成为便捷因其用起来比较简单,使用于少量的数据的存储和显示。
  • 因没有将视图与模型分离,所以没有视图类灵活,不能和任意的模型一起使用。

模型视图使用示例(查询本机文件系统)

  • 新建空项目testModelView,pro文件添加 QT += widgets,并添加main.cpp文件
    main.cpp文件代码:
#include <QApplication>
#include <QAbstractItemModel>       //抽象类模型
#include <QAbstractItemView>        //视图
#include <QItemSelectionModel>      //项选择模型
#include <QDirModel>                //目录模型
#include <QTreeView>                //树视图
#include <QListView>                //列表视图
#include <QTableView>               //表格视图
#include <QSplitter>                //窗口分割int main(int argc, char*argv[]){QApplication app(argc, argv);QDirModel model;       //创建目录模型QTreeView tree;         //创建树视图QListView list;      //创建列表视图QTableView table;       //创建表格视图tree.setModel(&model);  //树视图设置模型list.setModel(&model);  //列表视图设置模型table.setModel(&model); //表格视图设置模型//设置视图对象的选择方式为多选tree.setSelectionMode(QAbstractItemView::MultiSelection);list.setSelectionMode(tree.selectionMode());    //将树的选择方式传给列表table.setSelectionMode(tree.selectionMode());   //将树的选择方式传给表格//双击树视图后, 发射信号, 列表与表格视图刷新双击树视图的内容QObject::connect(&tree, SIGNAL(doubleClicked(QModelIndex)),&list, SLOT(setRootIndex(QModelIndex)));QObject::connect(&tree, SIGNAL(doubleClicked(QModelIndex)),&table, SLOT(setRootIndex(QModelIndex)));//设置窗口分割QSplitter *splitter = new QSplitter;splitter->addWidget(&tree);     //添加树模型splitter->addWidget(&list);       //添加列表模型splitter->addWidget(&table); //添加表格模型splitter->setWindowTitle("模型/视图"); //设置标题splitter->show();              //显示窗体return app.exec();
}

testModelview运行效果

标准模型项操作示例:

  • 新建空项目testQModelIndex,pro文件添加QT+= widgets,并添加main.cpp文件,编辑main.cpp文件代码
#include <QApplication>
#include <QTreeView>
#include <QStandardItemModel>
#include <QDebug>int main(int argc, char*argv[]){QApplication app(argc, argv);//创建标准项模型QStandardItemModel model;//获取标准项模型的根项, 根项是不可见的QStandardItem *parentItem = model.invisibleRootItem();//创建标准项QStandardItem *item_0 = new QStandardItem;item_0->setText("A");//设置图标QPixmap pixmap_0(50,50);    //设置宽和高为50pixmap_0.fill(Qt::red);     //设置颜色为红色item_0->setIcon(pixmap_0);  //为标准项设置图标item_0->setToolTip("A项的提示");  //设置工具提示parentItem->appendRow(item_0);parentItem = item_0;        //将 item_0 作为父项//创建 item_0 的子项QStandardItem *item_1 = new QStandardItem;item_1->setText("B");//设置 item_1 的图标QPixmap pixmap_1(50,50);pixmap_1.fill(Qt::blue);item_1->setIcon(pixmap_1);item_1->setToolTip("B项的提示");//将子项添加到父项下parentItem->appendRow(item_1);QStandardItem *item_2 = new QStandardItem;QPixmap pixmap_2(50,50);pixmap_2.fill(Qt::green);item_2->setData("C", Qt::EditRole);                     //设置文本,可编辑角色item_2->setData("C项的提示", Qt::ToolTipRole);         //工具提示角色item_2->setData(QIcon(pixmap_2), Qt::DecorationRole); //图标,渲染角色parentItem->appendRow(item_2);//在树视图中显示数据QTreeView view;view.setModel(&model);view.show();//获取信息QModelIndex index_A = model.index(0,0, QModelIndex());qDebug() << "index_A 包含行数: "<<model.rowCount(index_A);QModelIndex index_B = model.index(0,0, index_A);qDebug() << "index_B 文本信息:"<< model.data(index_B,Qt::EditRole).toString();qDebug() << "index_B 提示信息:"<< model.data(index_B,Qt::ToolTipRole).toString();return app.exec();
}

testModelIndex运行效果

自定义模型示例:军事武器模型

  • 新建空项目testCustomModel,pro文件添加QT+= widgets,并添加main.cpp文件
  • 添加c++类WeaponModel继承自QAbstractTableModel.
    编辑weaponmodel.h代码

weaponmodel.h

#ifndef WEAPONMODEL_H
#define WEAPONMODEL_H
#include <QAbstractTableModel>class WeaponModel : public QAbstractTableModel {public:WeaponModel(QObject *parent = 0);//重写父类的函数virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;virtual int columnCount(const QModelIndex &parent = QModelIndex()) const;QVariant data(const QModelIndex &index, int role) const;QVariant headerData(int section, Qt::Orientation orientation, int role) const;
private:QVector<short> m_army;            //军队QVector<short> m_weaponType;      //武器类型QMap<short,QString> m_armyMap;    //军队映射QMap<short,QString> m_weaponMap;  //武器映射QStringList m_weapon;             //武器链表QStringList m_header;             //武器表头void populateModel();             //初始化表格数据
};
#endif // WEAPONMODEL_H

weaponmodel.cpp

#include "weaponmodel.h"WeaponModel::WeaponModel(QObject *parent) : QAbstractTableModel(parent) {m_armyMap[1] = QString("空军");m_armyMap[2] = QString("海军");m_armyMap[3] = QString("陆军");m_armyMap[4] = QString("火箭军");m_weaponMap[1] = QString("轰炸机");m_weaponMap[2] = QString("战斗机");m_weaponMap[3] = QString("航空母舰");m_weaponMap[4] = QString("驱逐舰");m_weaponMap[5] = QString("武装直升机");m_weaponMap[6] = QString("坦克");m_weaponMap[7] = QString("洲际核导弹");m_weaponMap[8] = QString("超音速导弹");populateModel();
}int WeaponModel::rowCount(const QModelIndex &parent) const {//返回军队的行数return m_army.size();
}int WeaponModel::columnCount(const QModelIndex &parent) const {//返回列表头的列数return m_header.size();
}//返回索引的数据, 将数字映射成字符串
QVariant WeaponModel::data(const QModelIndex &index, int role) const {if(!index.isValid()) return QVariant(); //传入值无效if(role == Qt::DisplayRole){switch(index.column()){ //当前模型的列case 0:return m_armyMap[m_army[index.row()]];break;case 1:return m_weaponMap[m_weaponType[index.row()]];break;case 2:return m_weapon[index.row()];break;default:return QVariant();}}return QVariant();
}QVariant WeaponModel::headerData(int section, Qt::Orientation orientation, int role) const {if(role == Qt::DisplayRole && orientation == Qt::Horizontal){return m_header[section];}return QAbstractTableModel::headerData(section, orientation, role);
}void WeaponModel::populateModel() {//初始化表头m_header << QString("军种")<< QString("武器种类")<< QString("武器");//初始化军队数据m_army << 1 << 1 << 2 << 2 << 3 << 3 << 4 << 4;//初始化武器类型数据m_weaponType << 1 << 2 << 3 << 4 << 5 << 6 << 7 << 8;//初始化武器m_weapon << QString("B-2") << QString("歼-20")<<QString("山东舰") << QString("济南舰")<< QString("武直-10") << QString("99式步兵坦克")<< QString("东风-41") << QString("东风-17");
}

main.cpp

#include <QApplication>
#include <QTableView>
#include "weaponmodel.h"int main(int argc, char*argv[]){QApplication app(argc, argv);WeaponModel model;   //创建自定义模型QTableView view;   //创建表格视图view.setModel(&model);                //指定自定义模型在表格视图显示view.setWindowTitle("自定义表格视图"); //设置窗体标题    view.resize(400,300);                 //设置窗体大小view.show();                          //显示表格窗体return app.exec();
}

testCustomModel运行效果

Qt - MVC模型/视图编程相关推荐

  1. QT Model/View 编程:MVC模型视图编程:实例实现(二)

    目录 样例001:现有模型中使用视图Using views with an existing model 样例002:使用模型索引 样例003:使用模型 样例004:使用模型的多个视图 样例005:委 ...

  2. Qt - 模型/视图编程(MVC编程自定义模型)

    模型/视图编程 Qt中的模型/视图架构用来实现大量的数据存储.处理及显示.MVC(Model-View-Controller)包括了3个组件:模型(Model)是应用对象,用来表示数据:视图(View ...

  3. Qt 模型视图编程之表头设置

    背景 Qt 模型视图编程中模型定义了标准接口对数据进行访问,可根据需求继承对应的抽象模型类来实现自定义的数据模型.一个基本的数据模型至少要实现以下虚函数: ①.rowCount:行数,返回要显示多少行 ...

  4. [转载]Qt之模型/视图(实时更新数据)

    原文地址:Qt之模型/视图(实时更新数据)作者:一去丶二三里 上两节简单介绍了Qt中对于模型/视图的编程,大部分助手里说的很清楚了,现在就开始实战部分吧! 在实际应用中,视图展示的数据往往并非一成不变 ...

  5. [转载]Qt之模型/视图(实时更新数据)_vortex_新浪博客

    原文地址:Qt之模型/视图(实时更新数据)作者:一去丶二三里 上两节简单介绍了Qt中对于模型/视图的编程,大部分助手里说的很清楚了,现在就开始实战部分吧! 在实际应用中,视图展示的数据往往并非一成不变 ...

  6. Qt中模型/视图结构

    8.1 概述 MVC设计模式是起源于Smalltalk的一种与用户界面相关的设计模式.通过使用此模型,可以有效地分离数据和用户界面.MVC设计模式包括三个元素:表示数据的模型 (Model).表示用户 ...

  7. [转载]Qt之模型/视图(自定义风格)

    原文地址:Qt之模型/视图(自定义风格)作者:一去丶二三里 关于自定义风格是针对视图与委托而言的,使用事件与QSS都可以进行处理,今天关于美化的细节讲解一下. 先看下图: 先撇开界面的美观性(萝卜青菜 ...

  8. [转载]Qt之模型/视图(自定义风格)_vortex_新浪博客

    原文地址:Qt之模型/视图(自定义风格)作者:一去丶二三里 关于自定义风格是针对视图与委托而言的,使用事件与QSS都可以进行处理,今天关于美化的细节讲解一下. 先看下图: 先撇开界面的美观性(萝卜青菜 ...

  9. Qt 模型视图编程的简单实例

    导言: 当遇到一个相对复杂的项目软件的时候,处理的数据量相对较大,这时候从软件设计的角度,一般都会考虑运用模型视图的架构. Qt关于MVC编程组成部分: 大体上,模型.视图架构中众多类可以分为3组:模 ...

最新文章

  1. openssl、x509、crt、cer、key、csr、ssl、tls
  2. 使用java9的uuid生成方式,让uuid生成速度提升一个档次...
  3. [转] JSON转换
  4. Redis的API调用工具类
  5. 用gojs写的流程图demo
  6. 【已解决】Linux下安装JDK
  7. 1707: [Usaco2007 Nov]tanning分配防晒霜
  8. CSS面试总结(大致)
  9. 坐标定位手机元素_CSS 是如何影响浏览器元素在文档中的排列?
  10. 零基础学python难吗-终于明白0基础学python难吗
  11. 新一代最强开源UI自动化测试神器 Playwright - 元素定位
  12. 第一天:django+vue项目立项
  13. p5js动漫角色临摹
  14. Proxmox VE7.3+Ceph超融合私有云建设案例(低成本高价值,拿走不谢)
  15. linux shell编程从入门到精通pdf_SHELL脚本编程入门
  16. Windows预览体验计划空白等一些问题的解决办法
  17. 计算机的命令用英语怎么说,计算机外部和内部命令的英语及词汇
  18. Cocos Creator 编辑器扩展:Quick Finder
  19. mysqldump实战-问题2
  20. 提高代码质量之静态代码检查

热门文章

  1. 基于卷积神经网络的谣言检测(刘政(未志华)-计算机应用2017)
  2. lvs+keepalived+nginx实现高性能负载均衡集群
  3. 实力见证 ShowMeBug 入选 2021 中国新锐技术先锋企业
  4. 内存管理之DDR概念理解
  5. HTTP代理如何解决爬虫请求受限
  6. 最小系统八位灯的c语言程序,一个女生物联人的自学单片机笔记2021.1.23(单片机---点亮第一个LED灯)...
  7. C++【求水仙花数】输出所有的水仙花数。所谓“水仙花数”是指一个3位数,其各位数字立方和等于该数本身。例如:153是一个水仙花数,因为153=1^3+5^3+3^3。
  8. Flash 第十章 补间动画复习和引导动画
  9. 低级鼠标钩子WH_MOUSE_LL
  10. Atlas 200 DK 系列 --高级篇--模型转换