Qt Model-View架构领悟

news2024/12/29 1:00:36

1.架构的选择

1.1是否需要委托

模型视图架构图如下所示,模型视图架构源于MVC模式:模型(Model)是应用对象,表示数据;视图(View)是模型的用户界面,用以显示数据;控制(Controller)定义用户界面对用户输入的反应方式。模型视图架构相对于MVC模式有2个变化:

  • 1.将视图与控制两种组件结合在一起,在将数据的存储于数据可视化呈现进行分离同时,提供了较为简单的框架;
  • 2.引入了委托(Delegate,代理),用以对用户输入进行灵活处理,可以定制数据的渲染和编辑方式。
    在这里插入图片描述
    由于委托的引入,导致在使用模型视图架构时,存在对委托使用的选择策略问题。
    模型中的数据项的可视化一定程度上由其项角色决定,而其项角色比较有限,如下所示。

在这里插入图片描述
对于需要除了简单文本、图标等其它可视化呈现方式且需与用户进行较为复杂交互的数据项,采用委托方式,例如对现成的部件自定义委托(QLineEdit、QSpinBox、QComboBox、QProgressBar、QPixmap、QDateTimeEdit、QPushButton等)。委托基类依次包括QAbstractItemDelegate、QItemDelegate、QStyledItemDelegate。

继承QAbstractItemDelegate需实现paint()等方法实现自定义渲染(亦可创建委托控件),注意paint()方法的实现:数据可以另有数据类,作为该委托类的成员,数据类实现paint()方法,但在委托类中调用其数据成员执行paint()。另外其诸多虚方法中存在较多的QStyleOptionViewItem与QModelIndex的参数,便于自定义渲染样式。

相比于QItemDelegate,QStyledItemDelegate是默认的委托实现,更受Qt官方推荐(其使用当前的样式来绘制项目,当要实现自定义的委托或要和Qt样式表一起应用时,强烈建议使用)。2者需实现的几个虚方法主要是:createEditor、setModelData、setEditorData、updateEditorGeometry。需注意在setModelData中完成后发射closeEditor信号,通知视图确保编辑器部件被关闭与销毁,在编辑器编辑完成后发射commitData信号,提交到模型中(亦需发射closeEditor信号)。

Qt官方提供的例子里面强烈建议浏览学习

  • 1.以QStyledItemDelegate为基类的Spin Box Delegate Example、Star Delegate Example;
  • 2.以QAbstractItemDelegate为基类的Pixelator Example。

1.2模型/视图架构与图形视图框架的关系

图形视图框架提供了一个基于图形项的图形视图编程方法。由场景(QGraphicsScene)、视图(QGraphicsView)、图形项(QGraphicsItem)3部分组成,其中视图(QGraphicsView)对应视图(View),场景(QGraphicsScene)基本对应模型(Model),图形项(QGraphicsItem)则与委托类有类似之处,其存在交互,也负责自身的渲染(paint等方法)。

2.具体实现

2.1模型的选择策略

在这里插入图片描述

2.1.1QAbstractListModel

需要使用QListView显示数据,并配合自定义model时,我们从此类继承。仅用于一维数据模型。

子类化时,我们只需要实现rowCount()函数即可返回列表中的项目数,实现data()函数从列表中检索项目。
由于该模型代表一个一维结构,因此rowCount()函数返回模型中的项目总数。表现良好的模型还提供了HeaderData()实现。对于可编辑列表模型,还必须提供setData()的实现,并实现flags()函数,以便它返回包含Qt::ItemIsEditable的值。为可扩展列表的数据结构提供接口的模型可以提供insertRows()和removeRows()的实现。在实施这些功能时,重要的是调用适当的函数,以便所有连接的视图都知道任何更改:

	insertRows()实现必须在将新行插入数据结构之前调用beginInsertRows(),并且之后必须立即调用endInsertRows()。
	removeRows()实现必须在将行从数据结构中删除之前调用beginRemoveRows(),并且必须立即调用endRemoveRows()。

Qt官方提供了其的一个派生类QStringListModel,存储一个简单的QString项目列表。

2.1.2QAbstractTableModel

需要使用QTableView显示数据时,并配合自定义model时,我们从此类继承。仅用于二维数组模型。

rowCount()和columnCount()函数返回表的尺寸。要检索与模型中项目相对应的模型索引,请使用index()并仅提供行和列号。子类化QAbstractTableModel时,必须实现rowCount(),columnCount()和data()。 QAbstractTableModel提供了index()和parent()函数的默认实现。表现良好的模型还将实现HeaderData()。可编辑的模型需要实现setData(),然后实现flags()返回包含Qt::ItemIsEditable的值。为可扩展数据结构提供接口的模型可以提供insertRows(),removeRows(),insertColumns()和removeColumns()的实现。在实施这些功能时,重要的是调用适当的函数,以便所有连接的视图都知道任何更改:

	insertRows()实现必须在将新行插入数据结构之前调用beginInsertRows(),并且之后必须立即调用endInsertRows()。
	insertColumns()实现必须在将新列插入数据结构之前调用beginInsertCo​​lumns(),并且此后必须立即调用endInsertColumns()。
	removeRows()实现必须在将行从数据结构中删除之前调用beginRemoveRows(),并且此后必须立即调用endRemoveRows()。
	removeColumns()实现必须在将列从数据结构中删除之前调用beginRemoveColumns(),并且此后必须立即调用endRemoveColumns()。

QAbstractTableModel的一系列派生类QSqlQueryModel、QSqlTableModel、QSqlRelationTableModel,用来访问数据库。此处不赘述。

2.1.3QFileSystemModel

提供本地文件系统中文件和目录的信息。

2.1.4QStandardItemModel

可以作为QListView、QTableView、QTreeView的标准model。管理复杂的树型结构数据项,每个数据项可以包含任意的数据。

本模型具有内置的Item类:QStandardItem类,提供了一个用于QStandardItemModel类的项。Item通常包含文本,图标或复选框。每个Item都可以具有自己的背景刷,并使用setbackground()函数设置。当前的背景刷可以使用background()找到。每个Item的文本标签可以用自己的字体和刷子呈现。这些用setFont()和setForeground()函数指定,并使用font()和foreground()读取。默认情况下,项目是enabled, editable, selectable, checkable,并且可以用作drag、drop操作的来源,也可以用作drop的目标。可以通过调用setFlags()来更改每个Item的标志。可以使用setCheckState()函数检查可检查的Item。相应的checkState()函数指示是否已选中该Item。

可以通过调用setData()将特定于应用程序的数据存储在Item中。每个项目都可以包含二维子项表。这使得建立Item的层次结构成为可能。典型的层次结构是树,在这种情况下,子表是一个带有单列(列表)的表。

可以使用setRowCount()和setColumnCount()设置子表的尺寸。项目可以用setChild()将Item放在子表中。通过childe()方法获取指向子项的指针()。新的行和列也可以用insertRow()和insertColumn()插入,也可以与appendRow()和appendColumn()插入。使用附加功能和插入功能时,子表的尺寸将根据需要增长。
现有的子项可以使用removeRow()或takeRow()删除;相应地,可以使用removeColumn()或takeColumn()删除列。
可以通过调用sortChildren()对项目的孩子进行分类。

当子类化用于提供自定义项目时:

	可以为它们定义新类型,以便将它们与基类别区分开。应重新实现type()函数以返回等于或大于UserType的新类型值。
	如果要执行数据查询的自定义处理和/或控制项目\的数据表示如何表示,则重新实现data()和setData()。
	如果您希望QstandardItemModel能够按需创建自定义项目类的实例,需重新实现clone()。
	如果要控制项目的序列化形式表示如何表示项目,请重新实现read()和write()。
	如果要控制项目比较的语义,则重新实现operator<()。operator<()决定了用sortChildren()或QStandardItemModel:: sort()对Item进行排序顺序。

具有以下优点:

  • 1.实现代码简单,QStandardItemModel可以使用QStandardItem,通过不断添加子节点,从而构建出list、table、tree结构的数据。;
  • 2.该类使用QStandardItem存放数据项,用户不必定义任何数据结构来存放数据项;
  • 3.QStandardItem使用自关联关系,能够表达列表、表格、树甚至更复杂的数据结构,能够涵盖各种各样的数据集;
  • 4.QStandardItem本身存放着多个『角色,数据子项』,视图类、委托类或者其他用户定义的类能够方便地依据角色访问各个数据子项。
    缺点:
  • 1.当数据集中的数据项很多时,施加在数据集上的某些操作的执行效率会很低;
  • 2.数据太大时,占用内存巨大,性能低下。

QStandardItemModel vs QAbstractItemModel
在这里插入图片描述

  • 1.对于数据量小且不需要更新的场景,我们使用QStandardItemModel来实现比较简单,没有自定义model那么多代码逻辑。
  • 2.在数据量小,但是需要更新情况下,我们采用自定义model来实现,即使数据量小,更新数据其实也是比较慢的,它会占用较多UI线程时间,如果其他线程业务繁重,就会影响UI线程性能,导致界面卡顿。
  • 3.在数据量大情况下,无论更新与否,我们都采用自定义model来实现。

2.1.5QAbstractItemModel(建议重点关注)

需要使用QTreeView显示数据时,并配合自定义model时,我们从此类继承。

本模型为所有模型的祖宗基类。其定义了一个标准接口,供视图和委托来访问数据,数据本身不一定存储于模型中,也可以存储于数据结构、类、文件、数据库、其它组件内。其为数据提供了十分灵活的接口来处理各种视图,这些视图可以将数据表现为表格(table)、列表(list)、树(tree)等形式。对于一般的表格或者列表的数据结构,可以采用子类化QAbstractTableModel、QAbstractListModel或采用Qt官方提供的这2者的现场的派生模型来处理特定类型。对于更为通用的模型,以上的现成模型无法满足需求,则需自定义数据节点类(不强制继承QObject,但角色类似QStandardItem),形成树形的数据结构,与模型派生类配合完成模型层的功能。

个人建议复杂一些的数据,直接采用QAbstractItemModel派生类+自定义数据节点类

基础数据模型将视图和委托作为表的层次结构。如果不利用层次结构,则模型是一个简单的行和列表。每个项目都有QModelIndex指定的唯一索引。
在这里插入图片描述
可以通过模型访问的每个数据都有关联的模型索引。您可以使用index()函数获得此模型索引。每个索引可能具有sibling()索引;子项目具有parent()索引。

每个项目都有与之关联的许多数据元素,可以通过将role(请参见Qt::ItemDataRole)指定到模型的data()函数来检索。所有可用角色的数据可以使用itemData()函数同时获得。

可使用特定的Qt::ItemDataRole设置每个角色的数据。使用setData()单独设置单个角色的数据,也可以使用setItemData()设置所有角色。

可以使用flags()(请参阅Qt::ItemFlag)查询项目,以查看是否可以以其他方式选择,拖动或操纵它们。
如果项目具有子对象,则haschildren()返回相应的索引。

该模型在每个层次结构的每个级别上都有一个rowCount()和columnCount()。可以使用InserstRows(),insertColumns(),removeRows()和removeColumns()插入和删除行和列。

该模型发出信号以指示变化。例如,每当更改模型提供的数据项目时,都会发出dataChanged()。模型提供的标头更改会导致headerDataChanged()发出。如果基础数据的结构更改,则该模型可以发出LayoutChanged(),以指示任何附带的视图,应重新显示所显示的任何项目,考虑到新的结构。

可以使用Match()函数搜索通过模型可用的项。

要对模型进行排序,可以使用sort()。

在将QAbstractItemModel进行子类化时,至少必须实现index(),parent(),rowcount(),colundCount()和data()。这些功能用于所有只读模型,并构成可编辑模型的基础。
由于rowCount()的实现很昂贵,还可以重新实现haschildren()为实现模型特殊行为。这使得模型可以限制视图要求的数据量,并可以用作实施懒惰模型数据的一种方式。
要在模型中启用编辑,您还必须实现setData()和重新实现flags()以确保返回ItemIsEditable。还可以重新实现headerData()和setHeaderData()来控制模型的标头的显示方式。
分别重新实现setData()和setHeaderData()函数时,必须显式发射dataChanged()和headerDatachanged()信号
自定义模型需要为其他组件创建模型索引。为此,请用适合该项目的行和标识符来调用CreateIndex(),并以指针或整数值作为其标识符。这些值的组合对于每个项都必须是唯一的。自定义模型通常在其他重新实现功能中使用这些唯一标识符来检索项目数据并访问有关该项的父和子的信息。有关唯一标识符的更多信息,请参见Simple Tree Model Example示例。

不必支持Qt::ItemDataRole中定义的每个角色。取决于模型中包含的数据类型,仅实现data()函数以返回某些更常见的角色的有效信息可能才是有用的。大多数模型至少提供了Qt::DisplayRole的项目数据的文本表示,并且举止良好的模型还应为Qt::ToolTipRole、Qt::WhatsThisRole提供有效的信息。支持这些角色使模型可以与标准QT视图一起使用。但是,对于某些处理高度专业数据的模型,可能仅为用户定义的角色提供数据才是合适的。
为可扩展数据结构提供接口的模型可以提供insertRows(),removeRows(),insertColumns()和removeColumns()的实现。在实现这些功能时,重要的是要在发生之前和之后需向一切的连接视图通知有关模型尺寸更改:

inserstRows()实现必须在将新行插入数据结构之前调用beginInsertRows(),完成后立即调用endInsertRows()。
insertColumns()实现必须在将新列插入数据结构之前调用beginInsertColumns(),完成立即调用endInsertColunms()。
removeRows()实现必须在从数据结构中删除行之前调用beginRemoveRows(),完成立即调用endRemoveRows()。
removeColumns()实现必须在将列从数据结构中删除之前调用beginRemoveColumns(),完成立即调用endRemoveColumns()。

这些功能发出的私人信号使附件的组件有机会在任何数据都无法使用之前采取行动。使用这些开始和结束功能的插入和删除操作的封装也使模型可以正确管理持久模型索引(persistent model indexes)。如果希望选择正确处理,则必须确保调用这些功能。如果您插入或删除带子项的项,则无需为这些子项调用这些方法。换句话说,parent项将处理其子项。

要创建逐渐填充的模型,您可以重新实现fetchMore()和canFetchMore()。如果fetchMore()的重新实现将行添加到模型中,则必须调用beginInsertRows()和endInsertRows()。

Qt官方提供的例子里面强烈建议浏览学习(均为自定义数据结构):

  • 1.Simple Tree Model Example;
  • 2.Editable Tree Model Example。

2.2模型与数据的关系

在这里插入图片描述

模型项分为Qt定义的标准Item和用户自定义数据节点类,其特点都是完整的数据结构是树及其变种,另外自定义数据节点类需提供辅助功能接口,确保其对应的模型类能实现所必须的几个派生虚方法。

2.3内部通信方式

模型、视图、委托见使用信号槽实现通信:

  • 1.当数据源的数据发生改变时,模型发出信号告知视图;
  • 2.当用户与显示的项目交互时,视图发出信号来提供交互信息;
  • 3.当编辑项目时,委托发出信号,告知模型和视图编辑器的状态。

各模型、委托、视图存在大量的信号槽,需详细参考Qt帮助,比如QAbstractItemModel中更新数据后,记得发送信号dataChanged,显式通知视图刷新显式。

2.4代理模型

QAbstractProxyModel类为代理项目模型提供了一个可以执行排序,过滤或其他数据处理任务的基类。
此类定义了代理模型必须使用的标准接口,以便能够与其他模型/视图组件正确互动。它不应该直接实例化。
所有标准代理模型均来自QAbstractProxyModel类。如果您需要创建一个新的代理模型类,通常最好子类化一个已经存在且提供最接近期望的行为的类。
应该通过使用或子类化QSortFilterProxyModel创建过滤或从源模型中分类数据的代理模型。
要子类化QAbstractProxyModel,您需要实现mapFromSource()和mapToSource()。只有在需要不同于默认行为的行为时,才需要重新实现mapSelectionFromSource()和mapSelectionToSource()函数。
注意:如果源模型被删除或没有指定源模型,代理模型将在一个空占位符模型上操作。

2.5数据-窗口映射器

QDataWidgetMapper类在数据模型的一个区域和一个窗口部件间提供了一个映射,即可在一个窗口部件上显示和编辑一个模型中的一行数据。

2.6模型/视图架构下的style

以QTreeView举例,其绘制3剑客(QStyleOptionViewItem 样式直接决定渲染效果,需详加考察)

	drawBranches(QPainter *, const QRect &, const QModelIndex &) const
	drawRow(QPainter *, const QStyleOptionViewItem &, const QModelIndex &) const
	drawTree(QPainter *, const QRegion &) const

QTableView就没有这些可override的绘制虚方法,间接证明其通用性、可扩展性远远不如QTreeView。切记切记!

3.模型子类化

强烈建议阅读Qt官方的Model/View Programming,其中的模型子类化(Model Subclassing Reference)一节尤其需要细读。部分翻译如下:

模型子类需要提供在QAbstractItemModel基类中定义的许多虚函数的实现。需要实现的这些函数的数量取决于模型的类型——它是为视图提供一个简单的列表、一个表还是一个复杂的项目层次结构。从QAbstractListModel和QAbstractTableModel继承的模型可以利用这些类提供的函数的默认实现。在树状结构中公开数据项的模型必须为QAbstractItemModel中的许多虚拟函数提供实现。
需要在模型子类中实现的函数可以分为三组:

  • 1.项目数据处理:所有模型都需要实现一些功能,使视图和委托能够查询模型的维度、检查项目和检索数据。
  • 2.导航和索引创建:分层模型需要提供函数,视图可以调用这些函数来导航它们公开的树状结构,并获取项目的模型索引。
  • 3.拖放支持和MIME类型处理:模型继承了控制内部和外部拖放操作执行方式的函数。这些函数允许用其他组件和应用程序可以理解的MIME类型描述数据项。
    TODO

4.参考资料

【1】《Qt Creator快速入门 第3版》.霍亚飞
【2】 QTreeView使用系列教程.百里杨
【3】Qt助手

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

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

相关文章

springboot基础(78):Freemarker模板生成word文档

文章目录 前言如何使用Freemakrer生成word文档1. 制作模板2. 编写工具类 遇到的问题下载失败如何只生成文件不下载 前言 利用Freemarker模板生成word文档。示例&#xff0c;将左侧的模板生成为右侧的文档并下载。 如何使用Freemakrer生成word文档 1. 制作模板 1.编辑一份a…

实现注册与登录(企业级)

目录 实现注册超级管理员功能&#xff08;持久层&#xff09; 一、判定系统是否已经绑定超级管理员 二、编写保存用户记录的代码 三、编写查询用户ID的代码 实现注册超级管理员功能&#xff08;业务层&#xff09; 一、获取OpenId 二、编写注册新用户的业务代码 掌握 R…

tuple 和数组区别

元组&#xff08;tuple&#xff09;和数组&#xff08;array&#xff09;都是 Python 中用于存储多个值的数据结构&#xff0c;但它们在实现和使用上有一些区别。 元组是不可变的&#xff0c;而数组是可变的。即元组一旦创建&#xff0c;其内容就不能被修改&#xff0c;而数组…

高数笔记1(第一章函数 极限 连续 第一节函数第二节极限-极限的概念与性质)

目录 第一章 函数 极限 连续第一节 函数第二节 极限一、极限的概念与性质数列的极限例1例2 函数的极限极限的性质&#xff08;保号性重点 有界性&#xff09;例12例13例14 函数极限与数列极限的关系例15 第一章 函数 极限 连续 第一节 函数 判断有界要用函数的绝对值&#xff…

Toolformer:可以教会自己使用工具的语言模型

Toolformer&#xff1a;可以教会自己使用工具的语言模型 摘要Introduction现有大模型的局限处理办法本文的idea Approach样例化API调用执行API调用筛选API调用模型微调 实验局限 论文地址点这里 摘要 语言模型&#xff08;LMs&#xff09;呈现了令人深刻的仅使用少量的范例或…

2022(一等奖)D1649基于多源卫星遥感的干旱区农作物耗水精细模拟

作品介绍 1 研究背景及目标 1.1 研究区概况 本次研究的研究区位于甘肃省张掖市内。张掖市位于甘肃省西部&#xff0c;河西走廊中段&#xff0c;属干旱和半干旱两种气候类型&#xff0c;其特点是夏季短而酷热&#xff0c;冬季长而严寒&#xff0c;干旱少雨&#xff0c;且降水分…

MySQL-SQL存储过程/触发器详解(下)

♥️作者&#xff1a;小刘在C站 ♥️个人主页&#xff1a; 小刘主页 ♥️努力不一定有回报&#xff0c;但一定会有收获加油&#xff01;一起努力&#xff0c;共赴美好人生&#xff01; ♥️学习两年总结出的运维经验&#xff0c;以及思科模拟器全套网络实验教程。专栏&#xf…

ubuntu20.4服务器搭建ftp并连接(阿里云服务器)

首先在控制台添加ftp防火墙规则&#xff1a; 然后进入服务器安装ftp&#xff08;安装vsftpd&#xff09;: sudo apt update sudo apt install vsftpd使用以下命令检查其状态&#xff1a; sudo service vsftpd status如果FTP服务器未运行&#xff0c;请使用以下命令启动它&am…

强化学习:时序差分算法 TD-learning

例子引入 首先&#xff0c;我们考虑简单的平均估计计算&#xff1a; w E [ X ] wE[X] wE[X]&#xff0c;根据 RM算法 计算过程如下&#xff1a; 接着上面的例子&#xff0c;我们现在考虑一个较为复杂的问题&#xff0c;估计函数 v ( X ) v(X) v(X) 的平均值&#xff0c;根据 …

3.数据模型

文章目录 前言1.对象&#xff08;Object&#xff09;1.1 标准对象1.2 自定义对象1.2.1 创建一个property&#xff08;房产&#xff09;自定义对象1.2.2创建一个Favorite&#xff08;收藏夹&#xff09;自定义对象1.2.3 创建对象的注意事项 1.3 字段1.3.1 为property object创建…

迅镭激光参展CESC2023中国(江苏)国际储能大会,共话储能产业发展趋势!

2023年6月14日 中国(江苏)国际储能大会 暨智慧储能技术及应用展览会 在南京国际博览中心隆重开幕 迅镭激光携多款新能源解决方案 精彩亮相A区5C21展位 聚焦新能源电池绿色智能制造 共话储能行业创新发展之路 本次展会为期三天(6月14-16日) 诚邀广大行业同仁莅临参观交流! 本届大…

全志V3S嵌入式驱动开发(spi-nor驱动)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 所谓的spi nor驱动&#xff0c;其实就是让spi nor芯片&#xff0c;在linux kernel 5.2.y启动后可以被正确地识别到。前面有一篇文章&#xff0c;我…

POSIX信号量(基于生产消费模型)

目录 &#x1f34a;一、信号量 1.1之前代码的不足之处 1.2什么是信号量 &#x1f34a;二、信号量接口 &#x1f34a;三、信号量版本的生产消费模型 ①单生产单消费 ②多生产多消费 &#x1f34a;四、线程池 &#x1f34a;五、线程安全的单例模式 &#x1f34a;六、其他常…

大模型高效微调综述下: DiffPruning、BitFit、LoRa、AdaLoRA、MAM Adapters、UniPELT

文章目录 四、Selective Methods4.1 DiffPruning&#xff08;2020.10&#xff09;4.2 BitFit&#xff08;2021.6&#xff09;4.3 Freeze and Reconfigure (FAR&#xff0c;2022)4.4 FishMask&#xff08;略&#xff09; 五、Reparametrization-based methods&#xff08;重参数…

Selenium自动化工具集 - 完整指南和使用教程

文章目录 Selenium 的概述&#xff1a;Selenium 的安装与环境配置&#xff1a;Selenium WebDriver 的基本概念&#xff1a;定位元素的方法&#xff1a;常用操作方法&#xff1a;获取所有的 cookie&#xff1a;获取指定名称的 cookie&#xff1a;添加 cookie&#xff1a;删除指定…

JavaFX应用开发教程——基于JDK9与NetBeans实现

ISBN: 978-7-302-61499-9 作者&#xff1a;宋波 页数&#xff1a;257页 阅读时间&#xff1a;2023-06-18 推荐指数&#xff1a;★★★★★ 《JavaFX应用开发教程——基于JDK9与NetBeans实现》 是目前市面上讲解Java桌面开发为数不多的教材 &#xff08;JavaFX是Java语言的下一代…

Flutter系列(十二)实现购物车和提交订单页

基础工程&#xff1a; Flutter系列&#xff08;十一&#xff09;实现商城首页和商品详情页_摸金青年v的博客-CSDN博客 Flutter系列&#xff08;四&#xff09;底部导航顶部导航图文列表完整代码_摸金青年v的博客-CSDN博客 一、前言 本文用flutter实现购物车和提交订单页&#x…

【裸机开发】认识中断向量表(设置中断向量偏移的原因)

之前的LED驱动不存在中断&#xff0c;也就不包含中断的初始化。如果程序包含了中断&#xff0c;我们应还需要初始化哪些内容&#xff1f;要解决这个问题&#xff0c;我们需要先了解一个中断系统包含了哪些内容。 ① 中断向量表&#xff1a;描述中断对应的中断服务函数&#xf…

数据结构——栈的实现(动态增长版本)

堆栈&#xff08;stack&#xff09;又称为栈或堆叠&#xff0c;是计算机科学中的一种抽象资料类型&#xff0c;只允许在有序的线性资料集合的一端&#xff08;称为堆栈顶端&#xff0c;top&#xff09;进行加入数据&#xff08;push&#xff09;和移除数据&#xff08;pop&…

【软件架构】流水线设计模式

流水线模式 流水线模式是一种软件设计模式&#xff0c;它提供了构建和执行一系列操作的能力。 此模式最好与插件模式结合使用&#xff0c;以便在应用程序启动时动态构建流水线。 顺序 流水线的最基本实现是一个简单的操作序列。 public interface IOperation<T>{void …