<Qt> 信号和槽

目录

一、信号和槽概述

二、信号和槽的使用​​​​​​

(一)connect函数

(二)实现一个点击按钮关闭窗口的功能

(三)再谈connect

三、自定义槽函数

四、自定义信号

五、带参数的信号和槽

六、信号和槽存在的意义

七、信号和槽的断开

八、使用 Lambda 表达式来定义槽函数


一、信号和槽概述

        “信号”这个词在我们的日常生活中随处可见,比如:信号灯变绿,我们行人进行通行、鸡叫表示天亮了、下课铃响了代表着下课了、王者连跪表示我们该充钱了等等信号这个概念,在我们的生活中随处可见。从以上的例子中我们仔细观察的话其实是会发现,每一个信号后面都对应着我们的一个动作,比如:绿灯了,我们要通过人行道、鸡叫了我们要起床了、下课了我们要去干饭、王者连跪了我们要打开微信充钱…这些信号后面伴随的动作是怎么来到?或者说我们怎么知道接收到这些信号后该做什么?当然是生活经验、和老师学校教的反正不可能是临时起意嘛!换而言之就是这些信号后面代表的动作都是我们早已知道的!

        在Linux系统中,我们也介绍了信号的产生、信号的检测以及信号的处理机制,它就是系统内部的通知机制,也可以是一种进程间通信的方式。在系统中有很多信号,我们可以通过signal()函数捕捉信号,重写一个信号处理函数。在Qt中的信号也和系统中的信号有相似之处。

在QT中也是同理,信号就代表着用户发出了一个指令,而槽就代表着对于这个指令的处理方法!


  • 在Qt中,用户和控件的每次交互过程称为一个事件。比如"用户点击按钮"是一个事件,"用户关闭窗口"也是一个事件。每个事件都会发出一个信号,例如用户点击按钮会发出"按钮被点击"的信号,用户关闭窗口会发出"窗口被关闭"的信号。
  • Qt中的所有控件都具有接收信号的能力,一个控件还可以接收多个不同的信号。对于接收到的每个信号,控件都会做出相应的响应动作。例如,按钮所在的窗口接收到"按钮被点击"的信号后,会做出"关闭自己"的响应动作;再比如输入框自己接收到"输入框被点击"的信号后,会做出"显示闪烁的光标,等待用户输入数据"的响应动作。在Qt中,对信号做出的响应动作就称之为槽。
  • 信号和槽是Qt特有的消息传输机制,它能将相互独立的控件关联起来。比如,"按钮"和"窗口"本身是两个独立的控件,点击"按钮"并不会对"窗口"造成任何影响。通过信号和槽机制,可以将"按钮"和"窗口"关联起来,实现"点击按钮会使窗口关闭"的效果。

信号的本质
信号是由于用户对窗口或控件进行了某些操作,导致窗口或控件产生了某个特定事件,这时Qt对应的窗口类会发出某个信号,以此对用户的操作做出反应。因此,信号的本质就是事件。如:

  • 按钮单击、双击
  • 窗口刷新
  • 鼠标移动、鼠标按下、鼠标释放,
  • 键盘输入

在 Qt 中信号是通过什么形式呈现给使用者呢?

  • 我们对哪个窗口进行操作,哪个窗口就可以捕捉到这些被触发的事件。
  • 对于使用者来说触发了一个事件我们就可以得到Qt框架给我们发出的某个特定信号。
  • 信号的呈现形式就是函数,也就是说某个事件产生了,Qt 框架就会调用某个对应的信号函数,通知使用者。

槽的本质

(Slot)就是对信号响应的函数。槽就是一个函数,与一般的C++函数是一样的,可以定义在类的任何位置( public、protected 或private), 可以具有任何参数,可以被重载,也可以被直接调用(但是不能有默认参数)。槽函数与一般的函数不同的是:槽函数可以与一个信号关联,当信号被发射时,关联的槽函数被自动执行。

说明
(1) 信号和槽机制底层是通过函数间的相互调用实现的。每个信号都可以用函数来表示,称为信号函数;每个槽也可以用函数表示,称为槽函数。 例如: "按钮被按下"这个信号可以用clicked()函数表示,"窗口关闭"这个槽可以用close()函数表示,假如使用信号和槽机制实现: "点击按钮会关闭窗口"的功能,其实就是clicked()函数调用close()函数的效果。

(2) 信号函数和槽函数通常位于某个类中,和普通的成员函数相比,它们的特别之处在于:

  • 信号函数用 signals 关键字修饰,槽函数用public slots、protected slots或者private slots修饰。signals 和 slots 是Qt在C++的基础上扩展的关键字,专门用来指明信号函数和槽函数;
  • 信号函数只需要声明,不需要定义(实现) , 而槽函数需要定义(实现)。

信号函数的定义是Qt自动在编译程序之前生成的.编写Qt应用程序的程序员无需关注。这种自动生成代码的机制称为元编程(Meta Programming) .这种操作在很多场景中都能见到。


Qt中的信号也要涉及信号三要素:信号源、信号类型和信号处理方式:

  • 信号源:Qt中的信号是由某个控件发出的,Linux系统中可以是一个进程发送的信号。
  • 信号类型:用户不同的操作会触发不同的信号,例如点击按钮就会触发点击信号(clicked)、在输入框中移动光标也会触发相应的信号,我们写这样的GUI程序就是为了和用户交互,所以必须知道当前用户的具体操作,通过不同的操作进行不同的处理
  • 信号处理方式:在Qt中就引入了一个概念就是slot),说白了就是一个函数,再使用connect这样的函数把一个信号和一个槽关联起来,之后只要触发了信号,Qt就会自动执行槽函数,这种槽函数本质上也是一种回调函数

所以在Qt中一定要先关联信号和槽,也就是先要有槽函数并使用connect函数将二者关联起来,然后再触发这个信号,顺序不能颠倒

二、信号和槽的使用​​​​​​

(一)connect函数

上面既然说了,信号的三要素是:发送源、信号类型、处理方法,可是对于QT来说,它怎么知道哪一个信号该调用哪一个处理方法呢?也就是说,对于QT来说,它怎么知道某个信号该调用哪个处理方法呢?
当然,是我们开发人员提前将信号与处理方法之间的关系绑定好,到时候QT直接进行调用即可!

在 Qt 中,QObject类 中提供了一个静态成员函数 connect() ,该函数专门用来关联指定的信号函数和槽函数。

关于QObject类:
QObject类实际上是QT中所有内置类型的祖宗类!也就是说在QT中大部分类要么直接继承自QObject类,要么间接继承自QObject类,比如 QWidget 就继承自 QObject。与Java中的继承十分相似!
在QT中大概的继承关系如下(不准确的继承):

以下是 connect 的函数原型:

connect (const QObject *sender,const char *signal,const QObject *receiver,const char *method,Qt::ConnectionType type = Qt::AutoConnection)sender:   哪个控件发出的信号
signal:   发出的什么信号(信号函数) 
receiver: 谁接收这个信号
method:   怎么处理这个信号(接收信号的槽函数)
type:     用户指定关联方式,常用默认值,一般不需要手动设置.

connect 要求第一个参数和第二个参数是匹配的,比如第一个参数的类型如果是 QPushButton* ,那么第二个参数的信号必须是 QPushButton 内置的信号(父类的信号),不能是其他的一个类。

(二)实现一个点击按钮关闭窗口的功能

我们在窗口上设置一个按钮,当我们按下这个按钮就可关闭窗口。

分析: 当用户按下按钮控件过后,实际上是向QT发送了一个叫clicked的信号,为此我们现在要做的就是捕捉该信号,为该信号关联一个关闭函数,也就是对应Widget类中的 close() 函数

具体代码如下:

#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);// 点击按钮,窗口关闭QPushButton *button = new QPushButton(this); // 创建一个button对象button->setText("关闭"); // 设置按钮上的文本button->move(200, 200); // 设置按钮的位置connect(button, &QPushButton::clicked, this, &Widget::close);
}Widget::~Widget()
{delete ui;
}
  1. 创建一个QPushButton对象,想要点击这个按钮后就关闭这个窗口,发出信号的一定是QPushButton对象。
  2. 发出的信号一定是QPushButton内置的clicked信号。
  3. 要交给的对象就是this也就是Widget对象。
  4. 处理函数就可以使用Widget继承的QWidget内置的close()槽函数。

注意这里是 clicked,而不是 click:

运行程序后,点击按钮成功关闭窗口: 

(三)再谈connect

但是对以上的代码我们有两个疑问?

我们怎么知道点击一下按钮就会发出一个clicked信号?或者我们怎么知道QT有哪些信号或槽函数?

答:多看官方文档;当我们不了解某一个知识点的时候,官方文档是最好的学习工具,况且QT自己在也已经内置了官方文档:

如果我们要查找某一个类的信号的话,我们可以直接对这个类进行搜索,当然可能这个类中并没有包含整个信号,那么我们可以对这个类的父类、祖宗类进行搜索,这样的话我们一定可以找到这个信号,就比如上图的clicked信号,在QPushButton中就没有,但是在其父类QAbstractButton就存在:

找了一遍后发现没有找到clicked这样的信号,既然这样就要向它的父类中查找。 

QPushButton的父类就是QAbstractButton,通过类名我们也可以得知这是一个抽象类,在这个页面向下查找就找到了Signals这块,这里就有clicked等信号,也就类似于函数。

 对于槽函数我们也是如此:


在查看官方文档的时候,connect的原型如下 :

 第一个和第三个参数我们传入的是 QObject 子类指针,所以没有问题,但是第二个和第四个参数传入的是函数指针,但是为什么使用 const char* 来接收呢?( 并且这在C++中是绝对禁止的!) 就拿上面connect的例子举例,clicked的类型应该是void ( * ) () ,而close的类型应该是 bool ( * ) (),可是为什么这两个函数指针类型可以直接赋值给 const char*? 这两个的意义可不一样。

  • 原因就是这是旧版本的 connect 函数声明,是在对于信号传参的时候需要用SIGNAL宏修饰一下,对于槽函数传参的时候需要使用SLOT宏修饰一下,通过宏替换就可以把函数指针转换成 char*,这样就不会有类型不匹配的问题了。
  • 官方文档里的这个函数声明是旧版本的 connect 声明 ,正确写法是:
  • connect(button1, SIGNAL(&QPushButton::clicked), this, SLOT(&Widget::close))

从 Qt5 开始,对该写法进行了简化,不再需要写这两个宏了,所以上面的代码才能直接传入函数指针。Qt5 开始,给 connect 提供了重载版本,第二个参数和第四个参数成了泛型参数,允许传入任意类型的函数指针了。
点击 ctrl 然后鼠标点击 connect ,跳转到源码中查看:

这样的话,对于一个函数指针来说,它就不用再使用SIGNAL宏和SLOT宏来进行修饰了,根据模板的特性,它会自动推导传递过来的函数指针的类型,极其方便!同时新版的connect还使用了“类型萃取”技术,它可以帮助我们检查参数,发送源控件与信号类型是否匹配:若传入的第一个参数和第二个参数,或者第三个参数和第四个参数不匹配,(不匹配是指:2、4参数传入的函数指针,不是1、3参数的成员函数的指针。)代码出现编译错误。

三、自定义槽函数

纯代码

虽然QT已经给我们内置了许多对应的槽函数,但是在我们实际的开发中,我们更多的情况下,是结合自己的业务场景,针对对应的信号量身定做一个槽函数,也就是自定义槽函数。

自定义参函数的语法:

  1. 所谓的 slot 就是一个普通的成员函数,所以所谓的自定义一个槽函数,操作过程和自定义一个普通的成员函数没啥区别。
  2. 该成员函数需要使用public signals、private signals、protected signals来进行修饰。(在QT 5及以上版本中可以不用signal修饰)

为此,为了演示自定义槽函数,这也是上一篇也用过的,先使用纯代码的方式实现一下自定义槽。我们设计出一个具体的场景:

当用户点击按钮的时候就可以切换窗口标题。

分析: 当用户点击按钮的时候,实际上会发出一个clicked信号,现在对应的处理动作是将窗口标题改为:“捕捉到按钮信号”,为此我们需要捕捉clicked信号,并且自定义处理函数。

  • 还是要先new一个QPushButton对象,把点击信号和槽函数关联起来。
  • 槽函数中就设置为,捕捉到了信号就把Widget界面的标题修改一下。

具体代码如下:

widget.h:记得声明函数

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();// 自定义槽函数
//public slots:
//    void handleClicked();void handleClicked(); // 这两者自定义槽函数的方式都是可以的private:Ui::Widget *ui;
};
#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QPushButton *button = new QPushButton(this); // 创建一个button对象button->setText("按钮"); // 设置按钮上的文本button->move(200, 200); // 设置按钮的位置connect(button, &QPushButton::clicked, this, &Widget::handleClicked);
}Widget::~Widget()
{delete ui;
}void Widget::handleClicked()
{// 按下按钮,修改窗口标题this->setWindowTitle("捕捉到按钮信号");
}

运行程序,查看效果:

窗口标题成功修改: 

图形化界面

在 ui 界面,拖动 pushbutton 到编辑界面然后输入文字后,右键单击该按钮,选择 “转到槽” 

这个窗口为我们提供了 QPushButton 的所有信号,还包括了 QPushButton的父类信号。选择第一个信号:

点击确定或者双击就会跳转到编辑widget.cpp的界面,此时函数的声明和定义都已经自动生成好了,编写代码即可:

【注意】:这种方式是不会出现 connect() 函数的,Qt中除了connect可以连接信号和槽外,还可以通过函数名字的方式来自动连接,如上图所示函数名格式:on_ XXX_ SSS,其中:

  • 以"on"开头,中间使用下划线连接起来;
  • " XXX "表示的是对象名(控件的objectName)。
  • " SSS "表示的是对应的信号。
  • 如: " on_ pushButton_ _clicked() " , pushButton代表的是对象名,clicked 是对应的信号。

点击按钮,改变窗口的标题:


这里名字故意写错,就不能达到我们想要的效果:

这都是Qt中调用connectSlotsByName这个函数触发自动连接信号和槽,这个函数是在自动生成的ui_widget.h中setupUi函数中调用的。 

所以,如果是通过图形化界面创建控件,还是使用第二种方式快速连接信号和槽;如果是通过代码的方式创建控件,还是得手动调用connect函数,原因就是没有调用connectSlotsByName函数。

四、自定义信号

自定义信号很少用到。因为在GUI中,用户的操作行为是可以穷举的,Qt内置的信号已经覆盖到了大部分可能的用户操作,对于某些场景还是需要我们使用自定义信号的!

  • 信号是一种特殊的函数,程序员只需写出函数声明,并告诉Qt(需要使用slots关键字进行修饰),这是一个信号即可。这个函数的定义,是Qt在编译过程中,自动生成的(无法干预)。
  • 信号函数的返回值必须是void,有没有参数都可以,也支持函数重载。
  • 信号可以使用emit关键字进行发射(Qt5 emit不写也行)。

为此,我们根据该场景设计出一个具体的业务场景:

当用户点击按钮就可以切换窗口标题

signals是Qt自己扩展的关键字,qmake会调用代码分析和生成的工具,识别到signals这个关键字时就会把下面的函数声明认为是信号,并自动生成函数定义:

通过connect函数连接信号和槽函数就可以了,但是光连接还是不够的,还需要发送我们自定义的信号,这个emit也是Qt中的关键字,作用就是发送信号:

当点击按钮,就会触发on_pushButton_clicked函数,函数中就会发送mySignal信号,收到信号就会执行handleSignal自定义函数,之后就会修改窗口标题:

五、带参数的信号和槽

在自定义信号和槽函数的时候可以带上参数,并且QT允许重载信号和槽函数。信号在和槽函数进行绑定的时候,主要表现在以下两点:

  • 槽函数的参数类型必须和它绑定的信号的参数类型一致。
  • 槽函数的参数个数可以少于等于它绑定的信号的参数的个数。

参数的类型必须要一致,个数不一致是可以的,但是要求信号的参数的个数必须要比槽的参数多。

通过这一次连接信号和槽,并搭配不同参数就可以实现不同结果,可以让代码复用,就比如:

点击按按钮1,左上角标题改为标题1,点击按钮2,左上角标题改为标题2:

而且信号的参数比槽函数多也是可以的,但是不允许槽函数中的参数比信号中的多,原因就是:

  • 一个槽函数可能绑定多个信号。
  • 如果严格要求就意味着信号绑定到槽的要求变高了。
  • 所以信号的参数个数可以大于槽的参数个数,这样让信号和槽之间的绑定变得更灵活,更多的信号可以绑定到这个槽函数上。
  • 虽然个数不一致,但是槽函数会按照参数顺序拿前N个参数,这样就可以确保槽函数的每个参数都有值。

 还有一点就是,如果想要使用信号和槽的机制,就必须在类的一开始写上Q_OBJECT宏,否则会出现编译错误

当我们转到定义就可以看到这个宏中展开的代码,这里也有很多的宏,也会继续展开,最终实现相应的功能:

六、信号和槽存在的意义

信号和槽最主要就是要解决响应用户的操作,它在现在GUI框架中是一个有特色的机制,但是它的实现就没有那么简洁,但是它还要这样做就是为了:

  • 把触发用户操作的控件 和 处理用户的操作逻辑 解耦合。信号发送者不需要知道发出的信号被哪个对象的槽函数接收,槽函数也不需要知道哪些信号关联了自己,Qt的信号槽机制保证了信号与槽函数的调用。支持信号槽机制的类或者父类必须继承于QObject类。
  • 也想起到多对多的效果,一个信号可以connect到多个槽函数上,一个槽函数也可以被多个信号connect。(实际开发中,这种情况极少)

这就是可以把多个信号和多个槽函数绑定到一起:

缺点:

与回调函数相比,信号和槽稍微慢⼀些,因为它们提供了更高的灵活性,尽管在实际应用程序中差别不大。通过信号调用的槽函数比直接调用的速度慢约10倍(这是定位信号的接收对象所需的开销;遍历所有关联;编组/解组传递的参数;多线程时,信号可能需要排队),这种调用速度对性能要求不是非常高的场景是可以忽略的,是可以满足绝大部分场景。

七、信号和槽的断开

可以使用disconnect断开信号和槽的连接。但是大部分情况下,把信号和槽连接好就不用管了,主动断开的情况就是要把信号重新绑定到另一个槽函数上,如果不断开,这个信号发送就会触发两个槽函数。

  • 点击按钮修改标题:

  • 先点击断开原信号按钮,建立新连接,再点击修改标题按钮:

断开连接前,标题修改为旧标题,当点击下方pushButton后,上方原来的信号和槽断开了连接,重新绑定后,再点击上方pushButton,标题修改为新标题。

八、使用 Lambda 表达式来定义槽函数

Qt5在Qt4的基础上提高了信号与槽的灵活性,允许使用任意函数作为槽函数。
但如果想方便的编写槽函数,比如在编写函数时连函数名都不想定义,则可以通过Lambda表达式来达到这个目的。

Lambda表达式是C++11增加的特性。C++11 中的Lambda表达式用于定义并创建匿名的函数对
象,以简化编程工作。
Lambda表达式的语法格式如下:

[ capture ] ( params ) opt -> ret { Function body; 
};

局部变量引入方式 [ ]
[ ]:标识一个Lambda表达式的开始。不可省略。

  • 由于使用引用方式捕获对象会有局部变量释放了而Lambda函数还没有被调用的情况。如果执行Lambda函数,那么引用传递方式捕获进来的局部变量的值不可预知。所以绝大多数场合使用的形式为:={}
  • 早期版本的Qt,若要使用Lambda表达式,要在"pro"文件中添加:
    CONFIG += C++11
    

使用 Lambda 表达式的方式填写槽函数。这里的功能是点击一下按钮,按钮就移动到相应位置:

上述代码传值捕获没问题,传引用捕获会崩溃。原因是button局部变量(它指向的空间位于堆区,但其本身是一个局部变量的指针),构造函数结束后button变量即被销毁,生命周期结束,若传引用对这块非法空间进行访问就会造成程序崩溃。

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

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

相关文章

哈喽GPT-4o,程序员如何通过GPT-4o保护自己的合法权益

目录 一、法律研究Prompt&#xff1a;派遣合同和劳务外包合同有什么区别&#xff1f;详细说一下在被裁员时的区别&#xff1f; 二、法律条文检索Prompt&#xff1a;检索《劳动合同法》&#xff0c;以下情况属于第几条&#xff0c;如果公司进行技能考试&#xff0c;并以技能考试…

在Ubuntu上安装redis

Ubuntu上安装redis 一、通过下载redis的压缩包安装二、通过apt包管理器安装Redis三、修改redis的配置文件四、控制redis启动 Redis是一种开源的内存数据存储&#xff0c;可以用作数据库、缓存和消息代理等。本文将会介绍两种不同的安装方式&#xff0c;包括通过压缩包安装以及通…

求职学习day5

安排明天hr面 投一下平安可能。 hr面准备&#xff0c;复习java核心技术&#xff0c;复习java项目。 正视自己&#xff0c;调整心态。 也是很早接触了javaguide但是没有持续学习&#xff0c;项目介绍 | JavaGuide&#xff0c;面试前复习一下感觉还是很有收获的。 还有一些…

studio编译报错java.lang.NullPointerException

安卓studio编译报错&#xff0c;这个是一个新建的项目就报错&#xff0c;原因是 implementation androidx.appcompat:appcompat:1.7.0版本太高&#xff0c;修改后版本 implementation androidx.appcompat:appcompat:1.4.0&#xff0c; 编译又报错 18 issues were found wh…

【MQTT(3)】开发一个客户端,QT-Android安卓手机版本

手机版本更加方便 生成安卓库 参考了这个代码 在编译Mosquitto以支持安卓平台时&#xff0c;主要涉及到使用Android NDK&#xff08;Native Development Kit&#xff09;进行交叉编译。环境的准备参考之前的博客【QT开发&#xff08;17&#xff09;】2023-QT 5.14.2实现Andr…

视频联网共享平台LntonCVS视频监控汇聚平台视频云解决方案

LntonCVS流媒体平台是一款遵循国家GB28181标准协议的先进视频监控与云服务平台。该平台设计独特&#xff0c;能够同时接入并处理多路设备的视频流&#xff0c;支持包括RTSP、RTMP、FLV、HLS、WebRTC在内的多种视频流格式的分发。其功能丰富多样&#xff0c;涵盖了视频直播监控、…

进程与线程(一)进程相关

目录 一. 概念二 . 组成进程控制块程序段数据段 三. 特征四. 进程的状态与转换五. 进程控制进程创建进程终止进程阻塞与进程唤醒进程切换 六. 进程通信共享存储消息传递管道通信 一. 概念 多道程序环境下&#xff0c;允许多个程序并发执行&#xff0c;此时它们将失去封闭性&…

Linux-交换空间(Swap)管理

引入概念 在计算机中&#xff0c;硬盘的容量一般比内存大&#xff0c;内存&#xff08;4GB 8GB 16GB 32GB 64GB…&#xff09;&#xff0c;硬盘&#xff08;512GB 1T 2T…&#xff09;。 冯诺依曼的现代计算机结构体系里面的存储器就是内存 内存是一种易失性存储器&#xff0c…

路由数据获取及封装方法

数据库设计 自联表 定义tree字段 public class LabelValue{public int label { get; set; }public string? value { get; set; }public List<LabelValue> children { get; set; }}获取路由方法 public Response<object> getMenuList() {Response<object>…

利用patch-package补丁,解决H5预览PDF时电子签章不显示问题

利用patch-package补丁&#xff0c;解决H5预览PDF时电子签章不显示问题 一、问题描述 在生产环境中&#xff0c;遇到了一个紧急的技术问题&#xff1a;用户在移动端H5页面上查看电子票时&#xff0c;PDF文件预览功能正常&#xff0c;但其中的电子签章未能正常显示。这一问题直…

Linux网络——TcpServer

一、UDP 与 TCP 在现实生活中&#xff0c;Udp 类似于发传单&#xff0c;Tcp 类似于邮局的挂号信服务。 1.1 UDP&#xff08;用户数据报协议&#xff09; 无连接&#xff1a;发放传单时&#xff0c;你不需要提前和接受传单的人建立联系&#xff0c;直接把传单发出去。不可靠&…

0718vscode问答

终于来到 qt # Question 多态 # Answer 多态是面向对象编程中的一个重要概念&#xff0c;指的是同一个接口可以有多种不同的实现方式。多态性允许我们使用一个统一的接口来处理不同类型的对象&#xff0c;从而提高代码的灵活性和可扩展性。 在Java中&#xff0c;多态可以通过以…

处理.git文件夹过大出现臃肿问题

1、问题背景 在软件开发过程中&#xff0c;版本控制是一个至关重要的环节。Git 作为一种流行的分布式版本控制系统&#xff0c;被广泛应用于各种项目中。然而&#xff0c;近期我们发现在进行项目发版时&#xff0c;Git 克隆项目的时间显著增加&#xff0c;严重影响了发版的效率…

stm32入门-----EXTI外部中断(下——实践篇)

目录 前言 一、硬件介绍 1.对射红外线传感器 2.旋转编码器 二、EXTI外部中断C编程 1.开启RCC时钟 2.配置GPIOK口初始化 3.配置AFIO 4.配置EXIT 5.配置NVIC 三、EXIT外部中断项目实操 1.对射红外传感器计数 2.选择编码器计数 前言 本期接着上一期的内容继续学习stm3…

DHCP中继实验

一、什么是DHCP中继? 1、使得一个DHCP服务器同时为多个网段服务称为DHCP中继技术。 2、配置DHCP中继的网络设备可以在不同网段上从DHCP总服务器获取IP地址分配给下面的各个主机。 3、路由器和交换机都可充当中继。DHCP中继在两个网段间代理客户端和服务器请求,中继服务器需要…

postman双击打不开的解决方案

postman双击打不开的解决方案 深入再深入 于 2022-05-09 15:45:56 发布 阅读量3.1k 收藏 2 点赞数 4 文章标签&#xff1a; postman 版权 右键属性 安装路径 更新版本 回滚 问题排查 关键词由CSDN通过智能技术生成 解决方案&#xff1a; 右键-属性&#xff0c;复制安装路…

【数据集处理工具】根据COCO数据集的json标注文件实现训练与图像的文件划分

根据COCO数据集的json标注文件实现训练与图像的文件划分 一、适用场景&#xff1a;二、COCO数据集简介&#xff1a;三、场景细化&#xff1a;四、代码优势&#xff1a;五、代码 一、适用场景&#xff1a; 适用于一个常见的计算机视觉项目应用场景&#xff0c;特别是当涉及到使…

【漏洞复现】泛微e-cology9 WorkflowServiceXml SQL注入漏洞

文章目录 前言漏洞描述影响范围 漏洞复现nuclei脚本 安全修复 前言 泛微协同管理应用平台e-cology是一套兼具企业信息门户、知识文档管理、工作流程管理、人力资源管理、客户关系管理、项目管理、财务管理、资产管理、供应链管理、数据中心功能的企业大型协同管理平台。 漏洞…

FFmpeg播放视频

VS2017FFmpeg6.2.r113110SDL2.30.5 1.下载 ShiftMediaProject/FFmpeg 2.下载SDL2 3.新建VC控制台应用 3.配置include和lib 4.把FFmpeg和SDL的dll 复制到工程Debug目录下&#xff0c;并设置调试命令 5.复制一下mp4视频到工程Debug目录下&#xff08;复制一份到*.vcxproj同一目录…

系统架构设计师教程 第3章 信息系统基础知识-3.5 专家系统-解读

系统架构设计师教程 第3章 信息系统基础知识-3.5 专家系统(ES) 3.5.1 人工智能3.5.1.1 人工智能的特点3.5.1.2 人工智能的主要分支3.5.2 ES的概念3.5.2.1 ES 概述3.5.2.2 与传统程序的区别3.5.3 ES的特点3.5.4 ES的组成3.5.4.1 知识库3.5.4.2 综合数据库3.5.4.3 推理机3.5.4.…