Qt扫盲-QWidget理论使用总结

QWidget理论使用总结

  • 一、概述
  • 二、顶层 控件 和子 控件
  • 三、复合控件
  • 四、自定义控件和绘制
  • 五、大小提示和大小策略
  • 六、事件
  • 七、一组函数和属性
  • 八、QWidget样式表
  • 九、透明度和双缓冲
  • 十、创建半透明窗口

一、概述

widget 是用户界面的最小单位:它从window系统接收鼠标、键盘和其他事件,并在屏幕上显示自己。每个组件都是矩形的,并且按z轴顺序排列(就是窗口在屏幕里面层次的位置)。一个 控件 会被它的父 控件 和它前面的 控件 剪切。(其实就是被遮挡的意思)。

QWidget 是Qt里面其他控件的公共基类。

没有嵌入到父窗口中的控件称为窗口。通常,窗口有一个边框和一个标题栏,不过也可以使用适当的窗口标志创建没有这两个装饰的窗口)。在Qt中,QMainWindow 和 QDialog 的各种子类是最常见的窗口类型。

每个 控件 的构造函数都接受一到两个标准参数:

QWidget *parent = nullptr
  • QWidget *parent = nullptr 是新widget的父组件。如果它是nullptr(默认值),新 控件 将是一个窗口。如果不是,它将是parent的子元素,并受其父元素几何形状的限制(除非指定Qt::Window作为窗口标志)。
Qt::WindowFlags f = 0 
  • Qt::WindowFlags f = 0 (在可用的地方)设置窗口标志;默认值适用于几乎所有窗口组件,但如果要获得一个没有窗口系统框架的窗口,则必须使用特殊的标志。

QWidget有许多成员函数,但其中一些几乎没有直接功能;例如,QWidget有一个font属性,但它自己从不使用它,因为他也作为其他窗口的基类。其子类才提供了真正的功能,例如QLabel、QPushButton、QListWidget和QTabWidget等。

二、顶层 控件 和子 控件

没有父窗口的窗口始终是一个独立窗口(顶级窗口组件)。对于这些窗口组件,setWindowTitle() 和 setWindowIcon() 分别设置标题栏和图标。就像下图就能看出来是什么意思,设置窗口的图标和标题栏。

在这里插入图片描述

非窗口 控件 是子控件 ,显示在它们的父 控件 中。Qt中的大多数控件主要作为子控件使用。例如,可以将按钮显示为顶层窗口,但大多数人更喜欢将按钮放在其他 控件 中,如QDialog。
在这里插入图片描述

上图显示了一个QGroupBox小 控件 用于在QGridLayout提供的布局中保存各种子小 控件 。QLabel子 控件 已被概述以表明其完整尺寸。

三、复合控件

当一个小 控件 被用作一个 容器 来分组许多子小 控件 时,它被称为复合小 控件 。因为QWidget可以做容器来承载控件的。这些可以通过构建具有所需视觉属性的窗口组件(例如QFrame,QGroupBox)来创建,并向其中添加子窗口组件,通常通过布局来管理。上图使用的QGroupBox 了一个使用Qt Designer创建的复合组件。其实就是说用类似 QWidget 或者 QFrame 来作为其他控件的承载控件。其实可以理解为由父控件和子控件构成一起的控件可看成复合控件。

还可以通过继承标准窗口小 控件 (如QWidget或QFrame)并在子类的构造函数中添加必要的布局和子窗口小 控件 来创建复合窗口小 控件 。Qt提供的许多示例都使用这种方法,Qt教程中也介绍了这种方法。

四、自定义控件和绘制

由于QWidget是QPaintDevice的子类,可以使用子类来显示使用一系列绘制操作和QPainter类的实例组成的自定义内容。绘制就是自定义控件的一大利器,我们可以用绘制的方式绘制控件的外观,交互的话就可以用 鼠标事件或者在自定义控件里面添加对应的响应控件也可以响应,绘制主要是影响的外观。绘制的话也是绘制的背景,不会影响这个 QWidget内部的子控件。

这种方法与 Graphics View Framework 使用的canvas风格的方法不同,后者是由应用程序将项目添加到场景中,然后由框架自身渲染。

每个 控件 都在其 paintEvent() 函数中执行所有绘制操作。 每当控件需要重绘时,无论是由于某些外部更改还是应用程序请求重绘时,都会调用这个方法。我们需要做的就是重写这个函数就可以啦,就行下面的时钟例子,就用的绘制方式。

在这里插入图片描述

更为酷炫的,像这种的也是通过绘制的方式来制作的。
在这里插入图片描述

五、大小提示和大小策略

在实现新窗口组件时,几乎总是需要重新实现 sizeHint(),为窗口组件提供一个合理的默认大小,并使用 setSizePolicy() 设置正确的大小策略。

默认情况下,没有提供大小提示的复合 控件 将根据其子 控件 的空间需求进行调整。

size策略允许你为布局管理系统提供良好的默认行为,以便其他 控件 可以轻松地包含和管理你的 控件 。默认大小策略表明size提示表示窗口组件的首选大小,这对于许多窗口组件来说通常已经足够了。

注意:顶级 控件 的大小被限制为桌面高度和宽度的2/3。如果这些边界不够用,可以手动 resize() 控件 。

六、事件

QWidget 的 事件也是非常重要的,Qt的窗口相关事件系统基本上体现在 QWidget 的 基础函数里面,这些函数都可以让我们自己重写,然后扩展功能。

控件 响应通常由用户操作引起的事件。Qt通过调用特定的事件处理程序函数和包含每个事件信息的QEvent子类实例来向 控件 传递事件。

如果控件只包含子 控件 ,则可能不需要实现任何事件处理程序。如果要检测子 控件 中的鼠标点击,则在控件的mousePressEvent() 中调用子控件的 underMouse() 函数。
Scribble示例实现了一组更广泛的事件来处理鼠标移动、按钮按下和窗口大小调整。

您需要为自己的控件提供行为和内容,但下面是与QWidget相关的事件的简要概述,从最常见的开始:

事件名功能
paintEvent()每当控件需要重绘时,都会调用这个函数,每个显示自定义内容的小控件都必须实现它。使用QPainter进行绘制只能在paintEvent()或由paintEvent()调用的函数中进行。
resizeEvent()resizeEvent() 在控件被调整大小后被调用。
mousePressEvent()当鼠标指针在控件内部按下鼠标按钮,或者控件使用grabMouse()抓取鼠标时,会调用mousePressEvent()。在不松开鼠标的情况下按下鼠标,实际上与调用grabMouse()是一样的。
mouseReleaseEvent()mouseReleaseEvent() 在鼠标按键松开时调用。当widget接收到相应的鼠标按下事件时,它会接收鼠标释放事件。这意味着,如果用户在widget内按下鼠标,然后在释放鼠标按钮之前将鼠标拖动到其他地方,则widget将接收release事件。但有一个例外:如果鼠标按钮按下时出现一个弹出菜单,这个弹出菜单会立即窃取鼠标事件。
mouseDoubleClickEvent()mouseDoubleClickEvent() 在用户双击widget时被调用。如果用户双击,widget会接收到一个鼠标按压事件、一个鼠标释放事件、(一个鼠标点击事件) 、第二个鼠标按下事件、这个事件以及最后一个鼠标释放事件。(如果在操作过程中鼠标没有保持稳定,也可能会接收到一些鼠标移动事件。) 在第二次点击到来之前,无法区分是点击还是双击。(这就是为什么大多数GUI书籍建议双击是单击的扩展,而不是触发另一个动作的原因之一。)

接受键盘输入的控件需要重新实现以下几个事件处理程序。

事件名功能
keyPressEvent()每当按键被按下时,都会调用keyPressEvent()方法,当按键按下时间长到自动重复时,也会调用keyPressEvent()方法。只有当Tab和Shift+Tab键不被焦点改变机制使用时,它们才会被传递给widget。要强制小控件处理这些键,必须重新实现QWidget::event()。
focusInEvent()focusInEvent()在小控件获得键盘焦点时被调用(假设您已经调用了setFocusPolicy())。表现良好的控件以一种清晰而谨慎的方式表明它们拥有键盘焦点。
focusOutEvent()focusOutEvent()在小控件失去键盘焦点时被调用。

你可能还需要重新实现一些不太常见的事件处理程序:

事件名功能
mouseMoveEvent()mouseMoveEvent()会在鼠标移动而鼠标按钮按住不放时调用。这在拖放操作中很有用。如果调用setMouseTracking(true),即使没有按下任何按钮,也会得到鼠标移动事件。(参见拖放参考线。)
keyReleaseEvent()keyReleaseEvent()方法会在按键被释放时以及按键被按下时(如果按键是自动重复的)被调用。在这种情况下,widget将在每次重复时收到一对按键释放和按键按下事件。只有当Tab和Shift+Tab键不被焦点改变机制使用时,它们才会被传递给widget。要强制小控件处理这些键,必须重新实现QWidget::event()。
wheelEvent()每当用户在widget获得焦点时转动鼠标滚轮时,都会调用wheelEvent()。
enterEvent()enterEvent()在鼠标进入控件的屏幕空间时被调用。(这不包括组件的任何子组件拥有的屏幕空间。)
leaveEvent()当鼠标离开控件的屏幕空间时,会调用leaveEvent()。如果鼠标进入一个子控件,它不会导致leaveEvent()。
moveEvent()enterEvent()会在控件相对于其父控件被移动时调用。
closeEvent()closeEvent()在用户关闭控件时(或调用close()时)被调用。

在QEvent::Type的文档中还描述了一些相当模糊的事件。要处理这些事件,需要直接重新实现event()。

event()的默认实现处理Tab和Shift+Tab(移动键盘焦点),并将大多数其他事件传递给上面更专门的处理程序之一。

七、一组函数和属性

功能相关相关函数
窗口功能show(), hide(), raise(), lower(), close().
顶层窗口windowModified, windowTitle, windowIcon, isActiveWindow, activateWindow(), minimized, showMinimized(), maximized, showMaximized(), fullScreen, showFullScreen(), showNormal().
窗口内容update(), repaint(), scroll().
窗口几何pos, x(), y(), rect, size, width(), height(), move(), resize(), sizePolicy, sizeHint(), minimumSizeHint(), updateGeometry(), layout(), frameGeometry, geometry, childrenRect, childrenRegion, adjustSize(), mapFromGlobal(), mapToGlobal(), mapFromParent(), mapToParent(), maximumSize, minimumSize, sizeIncrement, baseSize, setFixedSize()
模式visible, isVisibleTo(), enabled, isEnabledTo(), modal, isWindow(), mouseTracking, updatesEnabled, visibleRegion().
观感style(), setStyle(), styleSheet, cursor, font, palette, backgroundRole(), setBackgroundRole(), fontInfo(), fontMetrics().
键盘焦点功能focus, focusPolicy, setFocus(), clearFocus(), setTabOrder(), setFocusProxy(), focusNextChild(), focusPreviousChild().
鼠标和键盘抓取grabMouse(), releaseMouse(), grabKeyboard(), releaseKeyboard(), mouseGrabber(), keyboardGrabber().
事件处理程序event(), mousePressEvent(), mouseReleaseEvent(), mouseDoubleClickEvent(), mouseMoveEvent(), keyPressEvent(), keyReleaseEvent(), focusInEvent(), focusOutEvent(), wheelEvent(), enterEvent(), leaveEvent(), paintEvent(), moveEvent(), resizeEvent(), closeEvent(), dragEnterEvent(), dragMoveEvent(), dragLeaveEvent(), dropEvent(), childEvent(), showEvent(), hideEvent(), customEvent(). changeEvent(),
系统功能parentWidget(), window(), setParent(), winId(), find(), metric().
上下文菜单contextMenuPolicy, contextMenuEvent(), customContextMenuRequested(), actions()
交互式帮助setToolTip(), setWhatsThis()
  • 窗口功能
    其实就是 控制窗口的 显示隐藏,关闭,以及窗口在屏幕里面的 Z-index 上移、下沉。
  • 顶层窗口
    控制窗口最大,最小化,全屏,激活、设置窗口图标或者标题等
  • 窗口内容
    窗口内容的刷新,重新绘制,滚动等等。
  • 窗口几何
    窗口的长宽大小、坐标位置等信息
  • 模式
    窗口的显示、隐藏、使能等
  • 观感
    窗口的样式,外观,字体、颜色等等
  • 键盘焦点功能
    就是输入的 焦点管理
  • 系统功能
    获取窗口的句柄,与Windows交互要多些

八、QWidget样式表

除了每个平台的标准窗口样式外,还可以根据样式表中指定的规则设置窗口小部件的样式。此功能使我们能够自定义特定部件的外观,以向用户提供有关其用途的视觉提示。例如,可以为一个按钮设置特定的样式,以表明它执行了破坏性操作。Qt提供的就是 QSS 样式表。

QSS 其实是Qt样式表,就是一种美化界面的方式。Qt样式表是Qt界面的一种强大的机制,可以让我们自定义窗口组件的外观。Qt样式表的概念、术语和语法很大程度上受到HTML层叠样式表(CSS)的启发。功能和CSS的基本一样,大家应该也是有CSS 的基本基础,那写QSS就很容易的。下面就是我对QSS的相关笔记

✔️ Qt扫盲-QSS概述 🏤
✔️ Qt扫盲-QSS语法概述 ♻️
✔️ Qt Designer配置QSS交互使用 ✈️
✔️ Qt扫盲-QSS定制Qt Widget控件 🌟
✔️ Qt扫盲-QSS帮助手册使用 ✨
✔️ Qt扫盲-QSS示例代码 🌵

九、透明度和双缓冲

自Qt 4.0以来,QWidget自动对其绘制进行双缓冲,因此不需要在paintEvent()中编写双缓冲代码以避免闪烁。

从Qt 4.1开始,Qt::WA_ContentsPropagated部 件属性已经被弃用。相反,只要没有设置Qt::WA_PaintOnScreen,父部件的内容就会默认传播到每个子部件。

我们可以编写自定义部件来利用这一特性,方法是更新不规则区域(以创建非矩形的子部件),或者使用小于完整alpha的组件绘制颜色。下图显示了如何微调自定义小部件的属性和属性以实现不同的效果。
在这里插入图片描述

在上图中,构建了一个移除区域的半透明矩形子部件,并将其添加到父部件(显示pixmap的QLabel)。然后,设置不同的属性和widget属性来实现不同的效果:

  • 左边的小部件没有其他属性或设置小部件属性。这个默认状态适合大多数使用透明度、形状不规则或者不使用不透明的画笔覆盖整个区域的自定义部件。
  • 中心部件设置了autoFillBackground属性。此属性与依赖widget提供默认背景的自定义部件一起使用,这些部件不会用不透明的画笔绘制整个区域。
  • 右边的部件设置了Qt::WA_OpaquePaintEvent部件属性。这表示部件将用不透明的颜色覆盖整个区域。小部件的区域最初是未初始化的,在图中以红色对角网格模式表示,该模式穿过覆盖的区域。WA_OpaquePaintArea属性对于需要快速绘制自己的专门化内容且不需要默认填充背景的部件非常有用。

要用简单的背景颜色快速更新自定义窗口组件,如实时绘图或绘图窗口组件,最好定义一个合适的背景颜色(使用带有QPalette::Window 的 setBackgroundRole()),设置 autoFillBackground 属性,并仅在窗口组件的 paintEvent() 中实现必要的绘图功能。

为了快速更新不断用不透明内容覆盖整个区域的自定义窗口组件(例如视频流窗口组件),最好设置窗口组件的Qt::WA_OpaquePaintEvent,避免与重绘窗口组件背景相关的任何不必要的开销。

如果窗口组件同时设置了Qt::WA_OpaquePaintEvent属性和autoFillBackground属性,则Qt::WA_OpaquePaintEvent属性优先。根据您的需求,您可以选择其中任何一个。

从Qt 4.1开始,父组件的内容也会传播到标准Qt组件。如果父部件以非标准的方式装饰,这可能会导致一些意想不到的结果,如下图所示。
在这里插入图片描述

在不借助于子类的情况下,定制标准Qt窗口组件的绘制行为的范围比定制窗口组件的范围要小一些。通常,标准窗口组件的期望外观可以通过设置其 autoFillBackground 属性来实现。

十、创建半透明窗口

从Qt 4.5开始,可以在支持合成的窗口系统上创建具有半透明区域的窗口。

要在顶级部件中启用此功能,请使用 setAttribute() 设置其Qt::WA_TranslucentBackground属性,并确保其背景在希望部分透明的区域中使用非不透明颜色绘制。
平台注意事项:

  • X11:此功能依赖于支持ARGB视觉效果的X服务器和合成窗口管理器的使用。
  • Window:窗口组件需要设置 Qt::FramelessWindowHint 窗 口标志,才能使半透明工作。

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

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

相关文章

Jsoup爬取简单信息

1. 豆瓣图书最受关注 1.1 创建SpringBoot项目或者Maven项目 1.2 引入jsoup <dependency><!-- jsoup HTML parser library https://jsoup.org/ --><groupId>org.jsoup</groupId><artifactId>jsoup</artifactId><version>1.15.3<…

Qt应用开发(基础篇)——堆栈窗口 QStackedWidget

一、前言 QStackedWidget继承于QFrame&#xff0c;QFrame继承于QWidget&#xff0c;是Qt常用的堆栈窗口部件。 框架类QFrame介绍 QStackedWidget堆栈窗口&#xff0c;根据下标切换&#xff0c;一次显示一个小部件&#xff0c;常用于应用界面切换、图片轮询播放等场景。 二、QSt…

中小企业体育代言:探索费用策略与实际操作

随着体育市场的不断扩大和企业品牌的不断提升&#xff0c;中小型企业正逐渐将目光投向了体育明星代言&#xff0c;希望通过这一策略来提升品牌知名度、美誉度&#xff0c;进而吸引目标消费者的注意力并提升销售量。然而&#xff0c;中小型企业请体育明星代言的费用究竟是多少呢…

element-ui的el-dialog,简单的封装。

el-dialog是使用率很高的组件 使用el-dialog很多都是按照文档的例子&#xff0c;用一个变量控制是否显示&#xff0c;再来一个变量控制标题。 如果我这个对话框多个地方使用的话还要创建多个变量&#xff0c;甚至关闭之后还要清空一些变量&#xff0c;应该可以简化一点。我写…

Windows Hyper-V Ubuntu 22.04 LTS安装

文章目录 Ubuntu准备Hyper-V启用虚拟化支持services.msc 打开服务列表&#xff0c;关注Hyper-V服务是否启动打开管理器创建虚拟机 启动备份 Ubuntu 下载Ubuntu-Desktop&#xff0c;这是个iso文件。 准备 20GB以上的磁盘空间&#xff0c;ubuntu安装后的虚拟磁盘文件超过15GB一…

C/C++test两步完成CMake项目静态分析

您可能一直在静态分析中使用CMake。但您是否尝试过将Parasoft C/Ctest与CMake一起使用吗&#xff1f;以下是如何使用C/Ctest在基于CMake的项目中运行静态分析的详细说明。 CMake是用于构建、测试和打包软件的最流行的工具之一。Parasoft C/Ctest通过简化构建管理过程&#xff…

【Minecraft】Fabric Mod开发完整流程1 - 环境配置与第一个物品

前言 Fabric 是 Minecraft 一款非官方的模组 API,与 Forge mod 不同。它以轻量级和高性能为设计目标,专注于支持新版本的 Minecraft。 Fabric 和 Forge 在各自的加载编译流程上差别很大&#xff0c;所以你很难看见有同时支持二者的 mod&#xff0c;除非做了兼容性处理 Fabri…

【Java笔记】对象存储服务MinIO

1 MinIO简介 MinIO基于Apache License v2.0开源协议的对象存储服务&#xff0c;可以做为云存储的解决方案用来保存海量的图片&#xff0c;视频&#xff0c;文档。由于采用Golang实现&#xff0c;服务端可以工作在Windows,Linux, OS X和FreeBSD上。配置简单&#xff0c;基本是复…

mac-右键-用VSCode打开

1.点击访达&#xff0c;搜索自动操作 2.选择快速操作 3.执行shell脚本 替换代码如下&#xff1a; for f in "$" doopen -a "Visual Studio Code" "$f" donecommand s保存会出现一个弹框&#xff0c;保存为“用VSCode打开” 5.使用

基于百度语音识别API智能语音识别和字幕推荐系统——深度学习算法应用(含全部工程源码)+测试数据集

目录 前言总体设计系统整体结构图系统流程图 运行环境模块实现1. 数据预处理2. 翻译3. 格式转换4. 音频切割5. 语音识别6. 文本切割7. main函数 系统测试工程源代码下载其它资料下载 前言 本项目基于百度语音识别API&#xff0c;结合了语音识别、视频转换音频识别以及语句停顿…

【人工智能124种任务大集合】-集齐了自然语言处理(NLP),计算机视觉(CV),语音识别,多模态等任务

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下人工智能124种任务大集合&#xff0c;任务集合主要包括4大类&#xff1a;自然语言处理&#xff08;NLP&#xff09;、计算机视觉&#xff08;CV&#xff09;、语音识别、多模态任务。 我这里整理了124种应用场景任…

工业物联网数据桥接教程:Modbus 桥接到 MQTT

Modbus 介绍 Modbus 是一种串行通信协议&#xff0c;用于连接工业自动化设备&#xff0c;最初由 Modicon 公司开发&#xff0c;诞生于 1979 年&#xff0c;现在已成为通用的通讯标准之一&#xff0c;广泛用于工业自动化场景。 Modbus 采用主从模式&#xff0c;支持多种传输方…

PyTorch深度学习实战(11)——卷积神经网络

PyTorch深度学习实战&#xff08;11&#xff09;——卷积神经网络 0. 前言1. 全连接网络的缺陷2. 卷积神经网络基本组件2.1 卷积2.2 步幅和填充2.3 池化2.3 卷积神经网络完整流程 3. 卷积和池化相比全连接网络的优势4. 使用 PyTorch 构建卷积神经网络4.1 使用 PyTorch 构建 CNN…

Linux学习之sed多行模式

N将下一行加入到模式空间 D删除模式空间中的第一个字符到第一个换行符 P打印模式空间中的第一个字符到第一个换行符 doubleSpace.txt里边的内容如下&#xff1a; goo d man使用下边的命令可以实现把上边对应的内容放到doubleSpace.txt。 echo goo >> doubleSpace.txt e…

sealos安装k8s

一、前言 1、我前面文章有写过使用 kubeadm 安装的方式&#xff0c;大家可以去参考 &#xff08;二&#xff09;k8s集群安装&#xff0c;有一系列的k8s文章说明 2、安装k8s的方式有很多 kubeadmsealoskubespray等等 3、关于sealos来安装 k8s &#xff0c;也是非常建议大家去…

Idea 反编译jar包

实际项目中&#xff0c;有时候会需要更改jar包源码来达到业务需求&#xff0c;本文章将介绍一下如何通过Idea来进行jar反编译 1、Idea安装decompiler插件 2、找到decompiler插件文件夹 decompiler插件文件夹路径为&#xff1a;idea安装路径/plugins/java-decompiler/lib 3、…

可独立创建应用的SaaS多租户低代码平台之租户的应用管理说明

在IT系统中&#xff0c;“租户”&#xff08;tenant&#xff09;通常用于指代一种多租户架构&#xff08;multi-tenancy&#xff09;&#xff0c;它是一种软件架构模式&#xff0c;允许多个用户或组织共享相同的应用程序或系统实例&#xff0c;但彼此之间的数据和配置被隔离开来…

C#软件外包开发框架

C# 是一种由微软开发的多范式编程语言&#xff0c;常用于开发各种类型的应用程序&#xff0c;从桌面应用程序到移动应用程序和Web应用程序。在 C# 开发中&#xff0c;有许多框架和库可供使用&#xff0c;用于简化开发过程、提高效率并实现特定的功能。下面和大家分享一些常见的…

代驾小程序怎么做

代驾小程序是一款专门为用户提供代驾服务的手机应用程序。它具有以下功能&#xff1a; 1. 预约代驾&#xff1a;代驾小程序允许用户在需要代驾服务时提前进行预约。用户可以选择出发地点、目的地以及预计用车时间&#xff0c;系统会自动匹配最合适的代驾司机&#xff0c;并确保…

div 中元素居中的N种常用方法

本文主要记录几种常用的div盒子水平垂直都居中的方法。本文主要参考了该篇博文并实践加以记录说明以加深理解记忆 css之div盒子居中常用方法大全 本文例子使用的 html body结构下的div 盒子模型如下&#xff1a; <body><div class"container"><div c…