QT基本组件与常用类

news/2024/5/6 14:31:24/文章来源:https://blog.csdn.net/m0_68210771/article/details/128437633

目录

一、设计师 Designer(掌握)

二、布局 Layout

2.1 布局的基本使用(掌握)

2.2 布局属性(掌握)

2.3 伸展器(掌握)

2.4 嵌套(掌握)

2.5 伸展与策略(了解)

2.6 代码布局(了解)

三、Designer连接信号槽(了解)

四、ui指针(掌握)

五、基本组件(掌握)

5.1 QWidget常用属性

5.2 标签 QLabel

5.3 按钮类

5.3.1 按钮类基本使用

5.3.2 按钮组 QButtonGroup

5.4 单行文本输入框 QQLineEdit

5.5 一组类似的组件

5.6 组合框 QComboBox

目录

一、设计师 Designer(掌握)

二、布局 Layout

2.1 布局的基本使用(掌握)

2.2 布局属性(掌握)

2.3 伸展器(掌握)

2.4 嵌套(掌握)

2.5 伸展与策略(了解)

2.6 代码布局(了解)

三、Designer连接信号槽(了解)

四、ui指针(掌握)

五、基本组件(掌握)

5.1 QWidget常用属性

5.2 标签 QLabel

5.3 按钮类

5.3.1 按钮类基本使用

5.3.2 按钮组 QButtonGroup

5.4 单行文本输入框 QQLineEdit

5.5 一组类似的组件

5.6 组合框 QComboBox

一、QString类(掌握)

二、容器类(掌握)

2.1 QList

2.2 QMap

三、Qt数据类型(熟悉)

3.1 Qt统一数据类型

3.2 Qt的通用数据类型QVariant

四、时间与日期(熟悉)

4.1 时间戳

4.2 格式化

4.3 相关UI组件

五、定时器 QTimer(掌握)


一、设计师 Designer(掌握)

Designer是一款用于设计Qt界面的程序,它生成的文件是.ui界面文件。

Designer程序可以独立启动,但是通常我们使用的是Qt Creator中内置的Designer程序,要使用内置的Designer程序,需要创建的Qt项目中包含.ui文件,因此创建一个带界面文件的Qt项目来使用Designer程序。

在Qt Creator中双击打开.ui文件,即可启动内置的Designer程序。

Designer程序的各个面板介绍如下:

二、布局 Layout

2.1 布局的基本使用(掌握)

可以把布局想象成一个“透明的盒子”,若干组件对象放置到“透明盒子”中,这些组件会按照“盒子”预设的规则自动排布。

本次讲解三种布局

  • 垂直布局 Vertical Layout

真正的类名叫QVBoxLayout

  • 水平布局 Horizontal Layout

真正的类名叫QHBoxLayout,与垂直布局相比,只有方向不同。

  • 格点布局 Grid Layout

真正的类名叫QGridLayout

2.2 布局属性(掌握)

垂直布局与水平布局属性相同:

2.3 伸展器(掌握)

当布局需要填充空间的时候需要一个辅助的组件:

伸展器,分为横向和竖向的。

2.4 嵌套(掌握)

布局可以嵌套,内层布局相当于外层布局的一个组件。

2.5 伸展与策略(了解)

QPushButton在垂直布局和水平布局中按照伸展比例设置时,表现出现象不同,原因是QPushButton组件中有一个sizePolicy属性控制的。

Minimum表示当缩小为最小时,不会继续缩小,但是可以放大。

Fixed表示大小不变。

除此之外,还有一些可选项,例如Maximum表示当放大到最大时,不再继续变大,但是可以缩小、Prefered(近似Expanding)缩小放大不受限制。

建议不要随意修改组件默认的策略,也就是说此属性适用于所有QWidget的派生类。

2.6 代码布局(了解)

除了上面使用Designer进行布局外,也可以通过C++代码进行布局。

需要新建一个不带ui界面文件的Qt项目。

dialog.h

#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
// 头文件
#include <QVBoxLayout>
#include <QPushButton>class Dialog : public QDialog
{
    Q_OBJECTpublic:
    Dialog(QWidget *parent = 0);
    ~Dialog();private:
    QVBoxLayout* layout; // 布局对象
    QPushButton* btn1;
    QPushButton* btn2;
};#endif // DIALOG_H

dialog.cpp

#include "dialog.h"Dialog::Dialog(QWidget *parent)
    : QDialog(parent)
{
    resize(300,300);
    btn1 = new QPushButton("按钮1",this);
    btn2 = new QPushButton("按钮2",this);
    // 创建布局对象
    layout = new QVBoxLayout(this);
    // 添加组件到布局中
    layout->addWidget(btn1);
    layout->addWidget(btn2);
}Dialog::~Dialog()
{
    delete layout;
    delete btn1;
    delete btn2;
}

从此往后,创建项目,再也不取消创建界面选项了,即后续的学习都使用ui界面文件。

三、Designer连接信号槽(了解)

Designer也可以连接信号槽,但是仅限于自带的信号,槽函数可以自动生成,也可以使用自带的。

在Designer中,点击键盘F4按钮,即可进入信号槽编辑状态。在编辑状态中,可以拖拽组件对象形成不同的信号槽连接,只需要在弹出的窗口中选择对应的函数即可。

配置好信号槽连接后,可以点击F3退出此模式。在普通模式下,也可以配置信号槽的连接,需要切换到“信号与槽编辑器”,如下所示。

在此面板中,所有的信号槽连接都以表格的方式进行展示,点击单元格也能配置。

除此之外,Designer也可以配置自带信号与自定义槽函数的连接,只需要选中组件对象后,点击鼠标右键的“转到槽”。

在弹出窗口中,可以选择当前组件适用的信号,如下所示。

选择信号函数后,Designer会自动在C++代码中生成对应的槽函数。程序员只需要在这个自动生成的槽函数中添加要执行的代码即可,无需适用connect连接,因为信号与槽函数已经连接好了。

在实际开发过程中,不建议使用Designer设计信号槽,仍然建议完全在C++代码中手动编写信号槽的相关代码,原因是使用Designer的方式会导致信号与槽的对应关系不明确,降低代码的可读性和可维护性。

四、ui指针(掌握)

实际上Designer程序的原理是,通过用户对图形化设计界面的拖拽和属性参数设置,自动生成.ui文件中的代码,而.ui文件中的代码是xml标签。

ui文件中的xml代码会在项目编译的过程,转换为C++代码,也就是说在Designer中设计的每个组件都会以C++对象的形式在这个步骤中创建。

通过ui指针可以获取和管理在Designer中设计的组件对象,包括对象的销毁,即ui指针销毁后,其管理的所有组件对象也一并销毁。

五、基本组件(掌握)

5.1 QWidget常用属性

在讲解各种不同的基本组件使用之前,先讲解一些常用的QWidget类的属性。

5.2 标签 QLabel

用来显示文字或图片,QLabel独有属性如下:

图片下载建议使用必应搜索:必应

图片导入项目的步骤如下:

1. 下载图片(jpg或png)后,命名为全小写英文,英文之间可以使用下划线分割。

2. 把图片放置到工作目录下。

3. 在Qt Creator中,选中项目,鼠标右键,点击“添加新文件”。

4. 在弹出的窗口中,按照下图所示进行操作。

5. 在弹出的窗口中,填写资源文件的民称后,点击“下一步”。

6. 在项目管理页面,直接点击“完成”。可以看到项目目录下多了一个.qrc格式的资源文件。

7. 选中.qrc资源文件,点击下方的

,在弹出的下拉菜单中,点击添加前缀,这一步只需要第一次操作即可。

8. 再次点击

,此时可以在弹出的下拉菜单中点击添加文件,点击“添加文件”后,弹出文件选择对话框,选择要添加的图片文件即可。

9. 可以在.qrc文件中看到刚刚添加的图片文件,后面就可以在项目中使用这张图片了。

设置图片到QLabel组件的方式如下:

  • 法一 通过Designer设置

先编译运行一遍程序(如果不这么做,Designer识别不了刚添加到资源文件中的图片),然后在Designer中选中QLabel组件,设置属性pixmap的值为显示的图片。需要注意的是,给pixmap属性设置图片时,要点击“选择资源”,而不是“选择文件”。

这种设置方式进行图像处理比较麻烦,最好在ps中处理好图片资源。

  • 法二

通过C++代码进行图片缩放,相比之下处理能力更好一些。

需要注意的是,尽量不要使用过大的图片,因为会增加程序的性能开销。

5.3 按钮类

5.3.1 按钮类基本使用

按钮类组件有QPushButton、QCheckBox、QRadioButton、QToolButton,分别表示按压式按钮、单选框、多选框和工具栏按钮。它们都有一个公共的基类:QAbstractButton,这个类规定了很多按钮的基本功能框架。

QAbstractButton常用属性有:

图标下载网站-阿里巴巴矢量图标库:iconfont-阿里巴巴矢量图标库

QAbstractButton常用信号如下:

5.3.2 按钮组 QButtonGroup

有的界面按钮很多,逐个按钮建立信号槽未免显得有些太过复杂。解决方法就是使用QButtonGroup按钮组。

QButtonGroup类仅仅是逻辑上的分组,并没有任何UI效果,也不属于UI组件,因此不归ui指针管理,需要程序员手动创建与销毁。

构造函数:

QButtonGroup(QObject * parent = 0)

只要parent参数不是QWidget类型的,说明此类不是UI相关类型,不归ui指针管理。

成员函数:

void addButton(QAbstractButton * button, int id = -1)

向按钮组中添加按钮对象

参数1:按钮对象

参数2:给按钮一个id号,要求正数且唯一

需要注意的是,多选按钮加到按钮组后会自动互斥,需调用下面的函数解除互斥。

group->setExclusive(false);

信号函数:

5.4 单行文本输入框 QQLineEdit

用于输入单行文本信息。

常用属性:

常用信号:

void textChanged(const QString & text)

每次文字发生变化时发射此信号,参数是新的文字

5.5 一组类似的组件

这一组组件的功能类似,包括:QSpinBox、ProgressBar、QSlider、QScrollBar、QDial,它们的继承结构如下所示:

各个组件的外观如下所示:

上面的组件有几个共同的属性:

  • maximum : int

最大值

  • minimum : int

最小值

  • value : int

当前值,通知信号:

void valueChanged(int value)

5.6 组合框 QComboBox

组合框用来代替QRadioButton等组件,可以点击之后弹出多个选项(英文:Item,中文译名为“项目”)。

常用属性:

常用信号:

一、QString类(掌握)

QString类是Qt的字符串类,采用Unicode编码,每个字符是一个16位的QChar,而不是8位的char,因此Qt可以完美地处理中文,并且一个中文字符算作一个字符长度。

由于在Unicode编码诞生之前,各国为自己的语言设计了本地的编码(如中文的GBK编码),在传输和转码过程中可能还会出现乱码问题,如果在Qt开发的过程中出现乱码问题,可以参考:从此乱码是路人

QString的函数相当多,不要去死记函数的固定使用,要求做到:

  • 记住函数中每个单词的意思
  • 用到的时候查文档

需要注意的是,QString类基本做到了兼容std::string的API

需要记住的函数词汇有:

append 向后追加

at 取出元素

begin 获取开始位置的迭代器

clear 清空

compare 比较

contains 包含

count 数量

endsWith 以...结尾

fill 每个元素填充

indexOf 出现的位置序号

insert 插入

isEmpty/isNull 是否为空,注意二者有差别

lastIndexOf 最后一次出现的位置下标

length 长度

prepend 向前追加

push_back 向后追加

push_front 向前追加

remove 移除

replace 替换

size 大小

split 分割

startsWith 以...开始

swap 交换

trimmed 去除空格

truncate 截取

类型转换示例代码:

    int i = 124;// 静态函数转换:数字→字符串
    QString s1 = QString::number(i);qDebug() << s1;// 成员函数转换:数字→字符串
    QString s2;
    s2.setNum(i);qDebug() << s2;// 字符串→数字
    QString str = "FF";bool ok;// 参数1:转换结果// 参数2:进制int hex = str.toInt(&ok,16);qDebug() << "转换后的数字是:" << hex; // 255qDebug() << "转换的结果是:" << ok; // true

【课堂练习】写一个函数输入一个字符串,返回值是bool,如果这个字符串符合电子邮件的地址则返回true,不符合返回false。

判断依据是:

  • 要有@
  • 要以.com结尾
  • 忽略大小写
  • @与.com之间有内容,且内容是数字或英文字母
  • @前面有英文或数字内容

二、容器类(掌握)

Qt的容器类相比C++的容器类更加轻巧、安全和易于使用,因为Qt对其进行速度和存储优化,可以减少可执行文件的大小;它们是线程安全的;在兼容C++容器类API接口的基础上,拓展了API接口。

本次学习顺序容器使用QList进行讲解,关联容器使用QMap进行讲解。

2.1 QList

QList是最常用的一种顺序容器,以增删改取遍历进行讲解演示。

到现在为止,Qt的课程中没有创建过任何一个用户自定义的类,下面手动创建一个基于C++的Student学生类,进行简单的封装后,把不同的学生对象存储到QList中。

创建自定义C++类的步骤如下:

1. 在Qt Creator中选中项目名称,鼠标右键,点击“添加新文件”。

2. 在弹出的窗口中,按照下图所示进行操作。

3. 在弹出的窗口,先输入新创建的C++类名,然后点击“下一步”。

4. 在项目管理页面,直接点击“完成”。可以看到项目中增加了对应头文件和源文件。

需要注意的是,QStringList类可以基本等同于QList<QString>

2.2 QMap

用法与C++中的map类似。

三、Qt数据类型(熟悉)

3.1 Qt统一数据类型

Qt是一个跨平台的开发框架,但是Qt依赖的C++语言并不是跨平台的,特别是很多基础的数据类型在不同的平台上可能会存在长度不一致的现象,所以当涉及跨平台需求时,Qt设计了一些可以保持统一长度的数据类型。

3.2 Qt的通用数据类型QVariant

QVariant类支持几乎所有的Qt常见的基本数据类型的转换。

    // 数字 → 字符串int a = 1;
    QVariant v(a);
    QString s = v.toString();qDebug() << s;// 字符串 → 数字
    QVariant v2(s);int b = v2.toInt();qDebug() << b;

四、时间与日期(熟悉)

Qt中使用QTime类来处理时间,使用QDate类来处理日期,这两个类合并为QDateTime,可以同时处理时间和日期。

以QDateTime类来说明时间和日期的处理方法。

4.1 时间戳

qint64 QDateTime::currentMSecsSinceEpoch() [static]

返回当前时间,格式为从1970-1-1 00:00:00 格林威治时间到现在的毫秒数。

可以利用上面的时间来作为生成随机数的种子。

    // 参数是随机数种子qsrand(QDateTime::currentMSecsSinceEpoch());// 产生一个0-9的随机数int rand = qrand()%10;qDebug() << "伪随机数:" << rand;

4.2 格式化

可以使用QDateTime对日期和时间进行格式化,函数如下:

QString QDateTime::toString(const QString & format) const

参数是一个字符串,为具体格式:

可以使用下面的函数来获取基于当前时区的当前时间和日期的QDateTime对象,当前指的是来自于系统数据。

QDateTime QDateTime::currentDateTime() [static]

    // 先获得一个基于当前的QDateTime对象
    QDateTime dt = QDateTime::currentDateTime();// 格式化
    QString text = dt.toString("yyyy-MM-dd hh:mm:ss");qDebug() << text;

4.3 相关UI组件

主要有QDateEdit、QDateTimeEdit、QTimeEdit和QCalendarWidget。

五、定时器 QTimer(掌握)

QTimer类与硬件定时器功能类似,主要完成两个功能:

  • 倒计时触发
  • 周期触发

常用属性:

主要通过singleShot的setter设定定时器是否为一次性,通过interva的setter设置定时器触发时间,然后调用启动函数:

void QTimer::start() [slot]

需要注意的是,如果定时器已经在运行了,再次调用start函数会停止定时器并重新运行。

如果定时器已经运行,也可以调用下面的函数停止定时器的运行:

void QTimer::stop() [slot]

当定时器触发时会发射以下信号:

void QTimer::timeout() [signal]

此类的对象需要手动创建:

QTimer::QTimer(QObject * parent = 0)

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

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

相关文章

分布式缓存的四大痛点

目前开发中经常用到的缓存&#xff0c;是我们必不可缺的&#xff0c;他大大的提高了我们整个项目的响应速度和并发量。但是带来好处的同时&#xff0c;也给我们带了了新的问题&#xff1a;缓存穿透、缓存击穿、缓存雪崩以及缓存一致性这么四个问题&#xff0c;也是分布式缓存的…

IT大侦“碳”:VxRail的可持续法宝

环境Environmental      社会责任Social Responsibility      企业治理Corporate Governance      随着碳达峰、碳中和的逐步推进,越来越多的“大厂”或各行业的明星企业都开始重视自己的ESG报告,已然成为了商界新风尚。      可持续发展战略也与前沿技术密切相…

Java项目:Springboot体育器材管理系统

作者主页&#xff1a;源码空间站2022 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文末获取源码 项目介绍 体育器材管理系统主要包含以下功能&#xff1a; 登录注册&#xff1b; 体育器材管理&#xff1a;显示器材表、显示价目表、显示供应商表&#x…

4.2、网络层提供的两种服务

1、面向连接的虚电路服务 虚电路服务的核心思想&#xff1a;可靠通信由网络自身来保证\color{red}可靠通信由网络自身来保证可靠通信由网络自身来保证 当两台计算机进行通信时&#xff0c;必须建立网络层的连接\color{red}网络层的连接网络层的连接----虚电路VC\color{red}虚…

Java+SpringBoot电影订票系统(含源码+论文+答辩PPT等)

项目功能简介: 该项目采用技术后台&#xff1a;SpringBoot、Spring、Springmvc、Springdata、MySQL数据库、前台&#xff1a;FreeMarker、css、Javascript等&#xff0c;项目含有源码、论文、配套开发软件、软件安装教程、项目发布教程等 项目功能介绍&#xff1a; 本系统主要的…

Hi,运维,你懂Java吗--No.4:JVM-概述

作为运维&#xff0c;你不一定要会写Java代码&#xff0c;但是一定要懂Java在生产跑起来之后的各种机制。 本文为《Hi&#xff0c;运维&#xff0c;你懂Java吗》系列文章 第四篇&#xff0c;敬请关注后续系列文章 欢迎关注 龙叔运维&#xff08;公众号&#xff09; 持续分享运…

筛法(线性筛,厄拉多塞筛)

在前前前前前前…的博客中,我们主要谈了欧拉筛和埃氏筛. 今天我们主要来聊一聊线性筛和厄拉多塞筛(其实和埃氏筛和欧拉筛本质上没区别哎).其实在这两种筛法中厄拉多塞筛最好懂(就连本蒟蒻一看代码就明白了…别看这个名字,容易糊弄人) 首先是厄拉多塞筛"粉墨登场"::…

某农业学校 算法设计与分析-第五次实验-回溯算法

1. 罗密欧与朱丽叶的迷宫问题 问题描述 罗密欧与朱丽叶的迷宫。罗密欧与朱丽叶身处一个mn的迷宫中&#xff0c;如图所示。每一个方格表示迷宫中的一个房间。这mn个房间中有一些房间是封闭的&#xff0c;不允许任何人进入。在迷宫中任何位置均可沿8 个方向进入未封闭的房间。罗…

深度学习常见概念字典(感知机、全连接层、激活函数、损失函数、反向传播、过拟合等)

这一章的所有内容均是为了进入深度学习具体的某某网络而准备的&#xff0c;简单但是非常有必要。 1. 神经网络&#xff08;neural networks&#xff09;的基本组成 1.1 神经元&#xff08;neuron&#xff09; 神经元&#xff08;neuron&#xff09; 是神经网络&#xff08;n…

Djiango实现用户管理增删改成功能实战

1.0定义 前后端不分离模式 前后端分离是指前端页面看到的效果都是由后端控制&#xff0c;即后端渲染HTML页面&#xff0c;前端与后端的耦合度比较高 前后端分离模式 后端仅返回前端所需要的数据&#xff0c;不在渲染HTML页面&#xff0c;不在控制前端的效果&#xff0c;至…

CodeQL代码静态污点分析引擎排查漏洞模式

文章目录前言环境搭建1.1 codeql基础1.2 vscode插件1.3 生成数据库1.4 HelloWorldcodeql语法2.1 语法结构2.2 常用类库2.3 谓词介绍2.4 污点分析漏洞检测3.1 初步结果3.2 解决误报总结前言 对于代码审计的工作&#xff0c;最早期的安全人员会以人工审计的方式来审计项目代码&a…

RabbitMQ 第二天 高级 7 RabbitMQ 高级特性 7.1 消息的可靠投递 7.1.1 confirm【确认模式】

RabbitMQ 【黑马程序员RabbitMQ全套教程&#xff0c;rabbitmq消息中间件到实战】 文章目录RabbitMQ第二天 高级7 RabbitMQ 高级特性7.1 消息的可靠投递7.1.1 confirm【确认模式】第二天 高级 7 RabbitMQ 高级特性 7.1 消息的可靠投递 7.1.1 confirm【确认模式】 在使用 Ra…

【数据预处理】基于Pandas的数据预处理技术【california_housing加州房价数据集】_后9个任务

文章目录一.需求分析二.需求解决2.1 对第一个特征&#xff08;收入中位数&#xff09;排序后画散点图2.2 对第一个特征&#xff08;收入中位数&#xff09;画分位数图并分析2.3 【选做】对所有特征画分位数图并进行分析2.4 使用线性回归方法拟合第一个特征&#xff08;收入中位…

【C语言进阶】指针练习题

写在前面 这是指有关指针的小题 正文 练习一 int main() {int a[5][5];int (*p)[4];pa;printf("%p,%d", &p[4][2]-&a[4][2], &p[4][2]-&a[4][2] );return 0; } 解析&#xff1a; a[4][2]为如图粉色部分&#xff0c;p[4][2]为如图蓝色部分。a的…

Java项目:springboot药品管理系统

作者主页&#xff1a;源码空间站2022 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文末获取源码 项目介绍 本项目属于前后端分离的项目&#xff0c;分为两个角色药品管理员和取药处人员 药品管理员&#xff1a; 登录、退出、药品信息录入、药厂信息录入…

买不到的数目(蓝桥杯C/C++A组真题详解)

题目详细&#xff1a; 题目思路&#xff1a; 对于这个题有一个定理 如果 a,b 均是正整数且互质&#xff0c;那么由 axby&#xff0c;x≥0&#xff0c;y≥0 不能凑出的最大数是 &#xff1a; a*b-a-b 具体的证明过程这里就不赘述 感兴趣的同学可以自行查找 这里就提供一种思…

RabbitMQ 第二天 高级 7 RabbitMQ 高级特性 7.2 Consumer Ack

RabbitMQ 【黑马程序员RabbitMQ全套教程&#xff0c;rabbitmq消息中间件到实战】 文章目录RabbitMQ第二天 高级7 RabbitMQ 高级特性7.2 Consumer Ack7.2.1 Consumer Ack7.2.2 Consumer Ack 小结7.2.3 消息可靠性总结第二天 高级 7 RabbitMQ 高级特性 7.2 Consumer Ack 7.2.…

C#语言实例源码系列-伪装文件

专栏分享点击跳转>Unity3D特效百例点击跳转>案例项目实战源码点击跳转>游戏脚本-辅助自动化点击跳转>Android控件全解手册 &#x1f449;关于作者 众所周知&#xff0c;人生是一个漫长的流程&#xff0c;不断克服困难&#xff0c;不断反思前进的过程。在这个过程中…

matlab神经网络求解最优化,matlab神经网络训练数据

1、神经网络的准确率是怎么计算的&#xff1f; 其实神经网络的准确率的标准是自己定义的。 我把你的例子赋予某种意义讲解&#xff1a; 1&#xff0c;期望输出[1 0 0 1]&#xff0c;每个元素代表一个属性是否存在。像着4个元素分别表示&#xff1a;是否肺炎&#xff0c;是否肝…

你可能不知道的DOM断点调试技巧

前言 作为一个前端&#xff0c;DOM断点应该是我们非常熟悉的&#xff0c;也是我们日常工作中经常要用到的一种调试技巧&#xff1b;但是下面这些DOM断点调试技巧你可能不知道&#xff0c;且听我一一道来。 监听元素 有这样一种场景&#xff0c;当DOM中某个元素移除或者元素属…