2023/9/18 -- C++/QT

news2024/11/23 19:32:39

作业

完善登录框

点击登录按钮后,判断账号(admin)和密码(123456)是否一致,如果匹配失败,则弹出错误对话框,文本内容“账号密码不匹配,是否重新登录”,给定两个按钮ok和cancel,点击ok后,会清除密码框中的内容,继续进行登录;如果点击cancel按钮,则关闭界面。

如果账号和密码匹配,则弹出信息对话框,给出提示信息为“登录成功”,给出一个按钮ok,点击ok后,关闭整个登录界面,跳转到其他界面

点击取消按钮后,弹出问题对话框,询问是否确定要退出登录,给出两个按钮,yes|no,点击yes,则直接关闭整个登录界面,如果点击no则进行进行登录

要求:消息对话框,对象版和静态成员函数版至少各实现一个

【免费】2023/9/18-C++/QT实现简易登录资源-CSDN文库icon-default.png?t=N7T8https://download.csdn.net/download/weixin_54147737/88354416

一、信号与槽机制

1.1 简介

1> 信号与槽机制,是qt引以为傲的、能够立于编程界而不倒的核心机制

2> 作用:实现多个组件之间的互相通信,一个组件发信号,另一个组件接收信号后,做相应的响应

3> 原理类似于IO中的两个进程间通过信号通信,但是,这里的信号,是可以传递信息的

1.2 信号与槽

1> 信号:信号函数,定义在类体内signals权限下的特殊成员函数,该函数是不完整的函数,只有声明,没有定义,返回值为void,参数就是传递的信息

2> 槽:槽函数,定义在类体内slots权限下的成员函数,该函数是完整的函数,既有声明也有定义,返回值为void类型,参数就是接收信号的信息

3> 槽函数可以被当作普通函数一样调用,但是普通函数不能当作槽函数一样连接信号

4> 信号函数和槽函数,不是标准的C++代码,通过moc.exe工具将其自动转化为标准的C++代码

5> 信号函数和槽函数可以是组件自带的,也可以由用户自定义,系统提供的每个组件都会自带信号与槽

6> 包含信号与槽的类体定义

class Widget : public QWidget
{
    Q_OBJECT            //有关信号与槽的元对象


signals:                    //该权限下定义属于自己的信号
    void my_signal();           //自定义一个无参无返回值的信号函数


private slots:
    void my_slot();                //自定义无参无返回值的槽函数


public:
    Widget(QWidget *parent = nullptr);
    ~Widget();


private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

1.3 信号与槽的连接

1> 基于ui界面的,手动选中信号与槽的连接,该连接只适用于系统提供的信号与槽的连接,连接函数也是由系统实现

2> 也是基于ui界面,在组件上右键转到槽,手动实现槽函数的内容,该方法只能更改槽函数逻辑,信号、连接都是由系统实现

3> qt4版本手动连接信号与槽,该连接是不友好的连接,因为两个宏的原因,它会将所有传递的数据都改成字符串类型

[static] QMetaObject::Connection               //返回值:是建立的信号与槽的连接,是一个静态成员函数
    QObject::connect(                          //函数名
        const QObject *sender,                 //信号发射者,是组件的指针
        const char *signal,                    //要发射的信号函数,函数是函数指针,要的是字符串类型,所以需要使用SIGNAL()宏进行转换后使用
        const QObject *receiver,                 //信号接收者,是组件的指针
        const char *method)                       //接收信号后,接收者要处理的槽函数,函数是函数指针,要的是字符串类型,所以需要使用SLOT()宏进行转换后使用
举个例子:
  QLabel *label = new QLabel;
  QScrollBar *scrollBar = new QScrollBar;
  QObject::connect(scrollBar, SIGNAL(valueChanged(int)),
                   label,  SLOT(setNum(int)));

4> qt5版本的信号与槽的连接

[static] QMetaObject::Connection            //返回值:是建立的信号与槽的连接,是一个静态成员函数
    QObject::connect(                 //函数名
        const QObject *sender,       //信号发射者,是组件的指针
        PointerToMemberFunction signal,    //信号函数的指针,要指定是哪个类中的哪个成员函数
        const QObject *receiver,              //信号接收者,是组件的指针
        PointerToMemberFunction method)    //槽函数的指针,要指定是哪个类中的哪个成员函数
举个例子:
  QLabel *label = new QLabel;
  QLineEdit *lineEdit = new QLineEdit;
  QObject::connect(lineEdit, &QLineEdit::textChanged,
                   label,  &QLabel::setText);

5> 信号连接功能函数

[static] QMetaObject::Connection          //返回值:是建立的信号与槽的连接,是一个静态成员函数
    QObject::connect(               //函数名
        const QObject *sender,          //信号发射者,是组件的指针
        PointerToMemberFunction signal,    //信号函数的指针,要指定是哪个类中的哪个成员函数
        Functor functor)            //功能函数:全局函数作为功能函数、仿函数作为功能函数、lambda表达式作为功能函数
举个例子1,全局函数作为功能函数:
  void someFunction();
  QPushButton *button = new QPushButton;
  QObject::connect(button, &QPushButton::clicked, someFunction);
  
  举个例子2:lambda作为功能函数
   QByteArray page = ...;
  QTcpSocket *socket = new QTcpSocket;
  socket->connectToHost("qt-project.org", 80);
  QObject::connect(socket, &QTcpSocket::connected, [=] () {
          socket->write("GET " + page + "\r\n");
      });

6> 信号与槽的断开

只需将之前的连接函数的connect改成disconnect即可,参数不变

1.4 信号的定义与发射

1、在类体的signals权限下,定义属于自己的信号

2、信号函数只有声明,没有定义,返回值为void,可用有参数

3、在程序所需处,使用关键字emit发射自定义的信号,格式:emit 信号名(实参);

4、信号函数可以连接到槽函数中,也可以连接另一个信号函数,表明发射第一个信号时,第二个信号跟着发射

1.5 信号与槽的总结

1> 一个信号可以连接多个槽函数

2> 一个槽函数可以连接多个信号函数

3> 一个信号函数可以连接到槽函数中,也可以连接另一个信号

4> 信号函数和槽函数参数个数

    1、信号函数和槽函数进行链接时,一般要求信号函数和槽函数的参数保持一致
        connect(信号发送者, SIGNAL(signalFun()),信号接收者, SLOT(slotFun()));     //Ok
        connect(信号发送者, SIGNAL(signalFun(int)),信号接收者, SLOT(slotFun(int)));     //Ok
        connect(信号发送者, SIGNAL(signalFun(int, char)),信号接收者, SLOT(slotFun(int, char)));     //Ok
        connect(信号发送者, SIGNAL(signalFun(char, int)),信号接收者, SLOT(slotFun(int, char)));     //False
        connect(信号发送者, SIGNAL(signalFun(int)),信号接收者, SLOT(slotFun(char)));     //False
    2、当信号函数的参数大于槽函数的参数时
        connect(信号发送者, SIGNAL(signalFun(int, char)),信号接收者, SLOT(slotFun()));     //Ok
        connect(信号发送者, SIGNAL(signalFun(int, char)),信号接收者, SLOT(slotFun(int)));     //Ok
        connect(信号发送者, SIGNAL(signalFun(int, char)),信号接收者, SLOT(slotFun(char)));     //False
    3、当信号函数的参数小于槽函数的参数时
        connect(信号发送者, SIGNAL(signalFun(int)),信号接收者, SLOT(slotFun(int, char)));     //False
        connect(信号发送者, SIGNAL(signalFun(int)),信号接收者, SLOT(slotFun(int, char=0)));     //Ok

1.6 使用信号与槽实现简单的页面跳转

1> 准备两个界面

2> 在第一个界面中,定义跳转的信号函数,第二个界面定义槽函数

3> 可以在主程序中实例化两个界面,第一个界面调用show函数,第二个不调用,并且在主调函数中将第一个界面的信号与第二个界面的槽函数连接

1) 头文件

widget.h

#ifndef WIDGET_H
#define WIDGET_H


#include <QWidget>
#include"second.h"


QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE


class Widget : public QWidget
{
    Q_OBJECT


public:
    Widget(QWidget *parent = nullptr);
    ~Widget();


signals:
    void jump();           //自定义跳转信号函数


private slots:
    void on_loginBtn_clicked();


private:
    Ui::Widget *ui;


    Second *s1;             //定义另一个界面的指针
};
#endif // WIDGET_H

second.h

#ifndef SECOND_H
#define SECOND_H


#include <QWidget>


namespace Ui {
class Second;
}


class Second : public QWidget
{
    Q_OBJECT


public slots:
    void jump_slot();         //接收跳转信号的槽函数


public:
    explicit Second(QWidget *parent = nullptr);
    ~Second();


private:
    Ui::Second *ui;
};


#endif // SECOND_H

2) 源文件

widget.cpp

#include "widget.h"
#include "ui_widget.h"


Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    s1 = new Second;            //给另一个界面实例化空间


    //将当前界面的信号,与s1界面的槽函数进行连接
    connect(this,&Widget::jump, s1, &Second::jump_slot);
}


Widget::~Widget()
{
    delete ui;
}




void Widget::on_loginBtn_clicked()
{
    emit jump();


    this->hide();        //将当前界面隐藏
}

second.cpp

#include "second.h"
#include "ui_second.h"






Second::Second(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Second)
{
    ui->setupUi(this);
}


Second::~Second()
{
    delete ui;
}


//接收跳转信号对应的槽函数
void Second::jump_slot()
{
    this->show();            //将自己界面进行展示
}

3) 主程序

#include "widget.h"
#include"second.h"


#include <QApplication>


int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();


    //Second s;           //定义第二个界面


    //连接w的信号与s的槽
    //QObject::connect(&w, &Widget::jump, &s, &Second::jump_slot);


    return a.exec();
}

二、对话框

2.1 消息对话框(QMessageBox)

1> 该类提供的消息对话框,用于提高用户的交互性,可以提供问题对话框、信息对话框、警告对话框、错误对话框。。。

2> 实现该对话框的方式有两种:基于属性版本、静态成员函数版本

3> 基于属性版本实现消息对话框:公共该类实例化对象,调用exec函数进入执行态,该函数返回值时用户点击的按钮

QMessageBox::QMessageBox(                             //构造函数函数名
    QMessageBox::Icon icon,                             //图标
    const QString &title,                                 //对话框标题
    const QString &text,                                    //对话框提示文本内容
    QMessageBox::StandardButtons buttons = NoButton,         //对话框提供的按钮,如果有多个按钮,则使用位或隔开
    QWidget *parent = nullptr)                                //父组件

参数1介绍,对话框提供的图标,该类中的枚举值

Constant
                        Value
            Description
QMessageBox::NoIcon
                0
                the message box does not have any icon.//不提供任何图标
QMessageBox::Question
              4
                an icon indicating that the message is asking a question.//提供一个问号图标
QMessageBox::Information
           1
                an icon indicating that the message is nothing out of the ordinary.//提供一个i符号图标
QMessageBox::Warning
               2
                an icon indicating that the message is a warning, but can be dealt with.//提供一个感叹号图标
QMessageBox::Critical
              3
                    an icon indicating that the message represents a critical problem.  //提供一个叉号图标

 参数4介绍,对话框上提供的标准按钮,时类中的枚举值,如果有多个按钮,中间有位或隔开 
Constant
                    Value
                Description
QMessageBox::Ok
            0x00000400
            An "OK" button defined with the AcceptRole.  //提供一个ok按钮
QMessageBox::Open
          0x00002000
            An "Open" button defined with the AcceptRole. //提供一个open按钮
QMessageBox::Save
          0x00000800
            A "Save" button defined with the AcceptRole.  //提供一个保存按钮
QMessageBox::Cancel
        0x00400000
            A "Cancel" button defined with the RejectRole. //提供一个取消按钮
QMessageBox::Close
         0x00200000
            A "Close" button defined with the RejectRole.  //提供一个关闭按钮
QMessageBox::Discard
       0x00800000
            A "Discard" or "Don't Save" button, depending on the platform, defined with the DestructiveRole.//不保存
举个例子:
 QMessageBox msgBox;               //实例化对象
  msgBox.setText("The document has been modified.");
  msgBox.setInformativeText("Do you want to save your changes?");
  msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
  msgBox.setDefaultButton(QMessageBox::Save);
  int ret = msgBox.exec();               //展示对话框
  
  //判断用户点击的结果
 switch (ret) {
    case QMessageBox::Save:
        // Save was clicked
        break;
    case QMessageBox::Discard:
        // Don't Save was clicked
        break;
    case QMessageBox::Cancel:
        // Cancel was clicked
        break;
    default:
        // should never be reached
        break;
  }



4> 基于静态成员函数版本:无需实例化对象,但是只能设置有限的信息

[static] QMessageBox::StandardButton             //函数返回值类型,是用户点击的标准按钮,该函数是静态成员函数
    QMessageBox::warning(                //函数名
        QWidget *parent,                  //父组件
        const QString &title,            //对话框标题
        const QString &text,             //对话框文本内容
        QMessageBox::StandardButtons buttons = Ok,     //提供的标准按钮,多个按钮用位或隔开
        QMessageBox::StandardButton defaultButton = NoButton)    //默认选中的按钮

举个例子:
  int ret = QMessageBox::warning(this, tr("My Application"),
                                 tr("The document has been modified.\n"
                                    "Do you want to save your changes?"),
                                 QMessageBox::Save | QMessageBox::Discard
                                 | QMessageBox::Cancel,
                                 QMessageBox::Save);

其余的静态成员函数

QMessageBox::StandardButton 
critical(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons = Ok, QMessageBox::StandardButton defaultButton = NoButton)
QMessageBox::StandardButton 
information(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons = Ok, QMessageBox::StandardButton defaultButton = NoButton)
QMessageBox::StandardButton 
question(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons = StandardButtons(Yes | No), QMessageBox::StandardButton defaultButton = NoButton)

5> 案例

1) 头文件

#ifndef WIDGET_H
#define WIDGET_H


#include <QWidget>
#include<QMessageBox>            //消息对话框类
#include<QDebug>


QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE


class Widget : public QWidget
{
    Q_OBJECT


public:
    Widget(QWidget *parent = nullptr);
    ~Widget();


private slots:
    void on_quesBtn_clicked();


    void on_warnBtn_clicked();


private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

2) 源文件

#include "widget.h"
#include "ui_widget.h"


Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
}


Widget::~Widget()
{
    delete ui;
}




//问题按钮对应的槽函数
void Widget::on_quesBtn_clicked()
{
    //1、调用构造函数实例化对象
    QMessageBox box(QMessageBox::Question,            //图标
                    "问题",                           //对话框标题
                    "晚上约不?",                       //对话框文本内容
                    QMessageBox::Yes | QMessageBox::No,   //提供的按钮
                    this);                                 //父组件
    box.setDetailedText("有上好的飞天茅台");         //提供详细文本内容
    box.setDefaultButton(QMessageBox::No);          //将no设置成默认按钮
    box.setButtonText(QMessageBox::Yes, "好的");
    box.setButtonText(QMessageBox::No, "没空");




    //2、调用exec函数运行对话框
    int ret = box.exec();


    //3、对结果进行判断
    if(ret == QMessageBox::Yes)
    {
        qDebug()<<"木的问题,老地方见";
    }else if(ret == QMessageBox::No)
    {
        qDebug()<<"下次一定";
    }
}






//警告按钮对应的槽函数
void Widget::on_warnBtn_clicked()
{
    //直接调用静态成员函数完成对话框的实现
    int ret = QMessageBox::warning(this,                      //父组件
                         "警告",                     //对话框标题
                         "放学等着,别走",               //对话框文本内容
                         QMessageBox::Yes|QMessageBox::No,   //对话题提供的按钮
                         QMessageBox::No);                 //默认选中的按钮


    //对用户选中的按钮进行判断
    if(ret == QMessageBox::Yes)
    {
        qDebug()<<"行,荤的还是素的,文的还是武的任你挑";
    }else if(ret == QMessageBox::No)
    {
        qDebug()<<"你永远是我大哥";
    }
}

三、加载资源文件

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

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

相关文章

《Linux运维总结:Centos7.6之OpenSSH7.4升级版本至9.4》

一、环境信息 操作系统&#xff1a;Centos7.6.1810 OpenSSH_7.4p1, OpenSSL 1.0.2k-fips 如下图所示&#xff1a; 注意&#xff1a;升级后由于加密算法的区别&#xff0c;低版本的SSH工具可能无法连接&#xff0c;建议改用Xshell7或SecureCRT9.0以上版本。 二、注意事项 1、检…

第九章 关系查询处理和查询优化

第九章 关系查询处理和查询优化 9.1 关系数据库系统的查询处理 9.1.1 查询处理步骤 查询分析 对查询语句进行扫描、词法分析和语法分析&#xff0c; 词法分析&#xff1a;从查询语句中识别出正确的语言符号。语法分析&#xff1a;进行语法检查。 查询检查 合法性检查视图转换…

【java】【SpringBoot】【二】运维实用篇 SpringBoot工程

目录 一、打包与运行 1、程序打包与运行&#xff08;Window版&#xff09; 1.1 打包 1.2 运行 1.3 打包插件 1.4 总结 1.6 命令行启动常见问题及解决方案 2、程序运行&#xff08;Linux版&#xff09; 二、配置高级 1、临时属性设置 2、配置文件分类 3、自定义配置…

Spring Boot + Vue3前后端分离实战wiki知识库系统十三--单点登录开发二

接着https://www.cnblogs.com/webor2006/p/17608839.html继续往下。 登录功能开发&#xff1a; 接下来则来开发用户的登录功能&#xff0c;先准备后端的接口。 后端增加登录接口&#xff1a; 1、UserLoginReq&#xff1a; 先来准备用户登录的请求实体&#xff1a; package com…

07JVM_内存模型和CAS与原子类

一、内存模型 1.java内存模型 Java内存结构是JMM&#xff08;Java Memory Model&#xff09;的意思。JMM定义了一套在多线程读写共享数据&#xff08;成员变量&#xff0c;数组&#xff09;时&#xff0c;对数据的原子性&#xff0c;见性&#xff0c;有序性的规则和保障。 1…

浅谈电力电容器技术的发展及选型

安科瑞 华楠 摘要&#xff1a;介绍了我国电力电容器产品制造技术的发展现状。在与国外电力电容器产品先进水平对比的基础上,讨论了我国电力电容器产品的差距和某些对策,并对我国电力电容器技术发展趋势提出了一些看法。 关键词&#xff1a;电力电容器;制造技术;技术发展 0 引…

每日一题~最大二叉树

题目链接&#xff1a;654. 最大二叉树 - 力扣&#xff08;LeetCode&#xff09; 题目描述&#xff1a; 给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建: 创建一个根节点&#xff0c;其值为 nums 中的最大值。递归地在最大值 左边 的 子数…

Logstash介绍

Logstash介绍 Logstash是一个开源数据收集引擎&#xff0c;具有实时管道功能。Logstash可以动态地将来自不同数据源的数据统一起来&#xff0c;并将数据标准化到你所选择的目的地。 集中、转换和存储你的数据 Logstash是一个开源的服务器端数据处理管道&#xff0c;可以同时从多…

采集分析仪设计原理图:437-带触摸显示的10路5Msps@18bit采集分析仪

带触摸显示的10路5Msps18bit采集分析仪 一、产品概述 本产品提供了多种传感器接入接口&#xff0c;支持多种类型传感器实时采集、处理、显示等功能。主处理器采用XC7Z100-FFG900芯片&#xff0c;具有444K逻辑单元和双核ARM Cortex-A9 MPCore处理器。PL部分得可编程逻辑可…

docker系列-报错以及解决指南

1. windows运行docker报错Windows Hypervisor is not presentDocker Desktop is unable to detect a Hypervisor.Hardware assisted virtualization and data execution protection must be enabled in the BIOS. Docker Desktop - Windows Hypervisor is not presentDocker D…

async和await的用法

定义 async的定义 在mdn中,async的定义为: async function 关键字可用于定义表达式中的异步函数。 其实很简单,就是async关键字后面定义的函数会被转化为一个异步的函数 如下所示: function fn1(){return 同步}async function asyncFn(){return 异步}console.log(fn1())con…

Dubbo3应用开发——架构的演变过程

Dubbo3应用开发——架构的演变过程 什么是Dubbo 早期Dubbo的定位&#xff1b; 基于Java的高性能&#xff0c;轻量级的RPC框架&#xff1b;SOA【Service-Oriented Architecture ⾯向服务的架构】 RPC服务治理&#xff1b; 2018年阿⾥巴巴把这个框架捐献给了 Apache 基⾦会&am…

深入理解Java单例模式和优化多线程任务处理

目录 饿汉模式懒汉模式单线程版多线程版双重检查锁定 阻塞队列 单例模式能保证某个类在程序中只存在唯一一份实例, 而不会创建出多个实例&#xff0c;并提供一个全局访问点。 饿汉模式 类加载的同时&#xff0c;创建实例。 class Singleton {private static final Singlet…

2023:生成式AI与存储最新发展和趋势分析(上)

生成式AI的热潮在短时间内席卷全球&#xff0c;以一种势不可挡的趋势迅速出圈&#xff0c;在某一时间段&#xff0c;似乎出现了“除了IT行业&#xff0c;人人都是AI专家”的盛况。这一轮如火如荼的全民AI热潮迸发至今&#xff0c;业已过半载&#xff0c;待最初的烟花绚烂散去&a…

【基础篇】六、基于SpringBoot来整合SSM的案例(下)

文章目录 1、前后端调用&#xff1a;axios发送异步请求2、添加功能3、删除功能4、修改功能5、异常消息处理6、分页功能7、分页Bug处理8、条件查询 接下来加入前端页面&#xff0c;使用axios发送异步请求调用上篇的接口。调前端代码时&#xff0c;发现还挺有趣&#xff0c;刷新、…

Learn Prompt-ChatGPT 精选案例:广告文案

ChatGPT 可以帮助我们生成广告文案和宣传图片&#xff0c;这对营销品牌建设很有帮助。通常&#xff0c;一个产品会有一个主要的广告词&#xff0c;传达设计理念或宣传产品的好处。我们可以尝试直接生成文案&#xff0c;看看 ChatGPT 有没有好的创意。假设我们的产品是一款登山鞋…

【css | linear-gradient】linear-gradient()的用法

linear-gradient() CSS函数创建一个由两种或多种颜色沿一条直线进行线性过渡的图像,其结果是<gradient>数据类型的对象,此对象是一种特殊的<image> 数据类型。 先看一个线上的示例 https://code.juejin.cn/pen/7277486410842996771 语法 /* 渐变轴为 45 度&…

Docker容器详解

值得看的原文地址

一根USB线,全新单片机开发体验!推荐WeCanStudio工具套件

我的需求 回想当初大学时代,学习单片机的开发最繁琐的事情就是,通过串口升级STC的MCU来调试编写的固件。不知到有多少个深夜都在重复以下步骤&#xff1a; Keil编译代码打开STC软件,选择对生成的新固件程序手动断电、上电MCU板子(USB转串口的驱动还经常让电脑蓝屏&#x1f6…

极智开发 | 制作u盘启动盘的几种方式

欢迎关注我的公众号 [极智视界],获取我的更多经验分享 大家好,我是极智视界,本文分享一下 制作u盘启动盘的几种方式。 邀您加入我的知识星球「极智视界」,星球内有超多好玩的项目实战源码和资源下载,链接:https://t.zsxq.com/0aiNxERDq 在平时的工作、生活中,经常会涉及…