【QT】信号与槽(概述、使用、自定义、连接方式、其他说明)

一、信号和槽概述

在 Qt 中,用户和控件的每次交互过程称为一个事件。比如 “用户点击按钮” 是一个事件,“用户关闭窗口” 也是一个事件。每个事件都会发出一个信号,例如用户点击按钮会发出 “按钮被点击” 的信号,用户关闭窗口会发出 “窗口被关闭” 的信号。

Qt 中的所有控件都具有接收信号的能力,一个控件还可以接收多个不同的信号。对于接收到的每个信号,控件都会做出相应的响应动作。例如,按钮所在的窗口接收到 “按钮被点击” 的信号后,会做出 “关闭自己” 的响应动作;再比如输入框自己接收到 “输入框被点击” 的信号后,会做出 “显示闪烁的光标,等待用户输入数据” 的响应动作。在 Qt 中,对信号做出的响应动作就称之为

信号和槽是 Qt 特有的消息传输机制,可以通过 connect 这样的函数,把一个信号和一个槽这种相互独立的控件关联起来。比如,“按钮” 和 “窗口” 本身是两个独立的控件,点击 “按钮” 并不会对 “窗口” 造成任何影响。通过信号和槽机制,可以将 “按钮” 和 “窗口” 关联起来,实现 “点击按钮会使窗口关闭” 的效果。


1、信号的本质

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

  • 按钮单击、双击
  • 窗口刷新
  • 鼠标移动、鼠标按下、鼠标释放
  • 键盘输入
那么在 Qt 中信号是通过什么形式呈现给使用者的呢?
  • 我们对哪个窗口进行操作, 哪个窗口就可以捕捉到这些被触发的事件。
  • 对于使用者来说触发了一个事件,我们就可以得到 Qt 框架给我们发出的某个特定信号。

  • 信号的呈现形式就是函数, 也就是说某个事件产生了, Qt 框架就会调用某个对应的信号函数,通知使用者。

在 Qt 中信号的发出者是某个实例化的类对象。


2、槽的本质

槽(Slot)就是对信号响应的函数槽就是一个函数,与⼀般的 C++ 函数是⼀样的,可以定义在类的任何位置(public、protected 或 private),可以具有任何参数,可以被重载,也可以被直接调用(但是不能有默认参数)

槽函数与一般的函数不同的是:槽函数可以与一个信号关联,当信号被发射时,关联的槽函数被自动执行

所谓的 “槽函数” 本质上也是一种 “回调函数”(callback)

【C 语言阶段 - 函数指针】

  • 实现转移表,降低代码的 “圈复杂度”
  • 实现回调函数效果(qsort)

【C++ 阶段】

  • STL 中,函数对象 / 仿函数
  • lambda 表达式

【Linux】

  • 信号处理函数
  • 线程的入口函数
  • epoll 基于回调的机制

(1)信号和槽机制底层是通过函数间的相互调用实现的

每个信号都可以用函数来表示,称为信号函数;每个槽也可以用函数表示,称为槽函数

例如:“按钮被按下” 这个信号可以用 clicked() 函数表示,“窗口关闭” 这个槽可以用 close() 函数表示,假如使用信号和槽机制 - 实现:“点击按钮会关闭窗口” 的功能,其实就是 clicked() 函数调用 close() 函数的效果。


(2)信号函数和槽函数通常位于某个类中

和普通的成员函数相比,它们的特别之处:

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

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

二、信号和槽的使用

1、连接信号和槽

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


(1)关于 QObject

QObject 是 Qt 内置的父类,Qt 中提供的很多类都是直接或者间接继承自 QObject。(在 Java 中也存在相似的设定)


(2)connect()

A. 函数原型
connect (const QObject *sender,    //描述当前信号是哪个控件发出的const char * signal ,      //信号类型const QObject * receiver , //信号如何处理(哪个对象处理)const char * method ,      //信号如何处理(这个对象该怎么处理——要处理信号的对象提供的成员函数)Qt::ConnectionType type = Qt::AutoConnection ) //暂时不考虑,很少使用

B. 参数说明
  • sender:信号的发送者。

  • signal:发送的信号(信号函数)。

  • receiver:信号的接收者。

  • method:接收信号的槽函数

  • type:用于指定关联方式,默认的关联方式为 Qt::AutoConnection,通常不需要手动设定。


C. 代码示例

在窗口中设置一个按钮,当点击 “按钮” 时关闭 “窗口”:


2、查看内置信号和槽

系统自带的信号和槽通常是通过 “Qt 帮助文档” 来查询的。如上述示例,要查询 “按钮” 的信号,在帮助文档中输入:QPushButton

首先可以在 "Contents" 中寻找关键字 signals如果没有找到,继续去父类中查找,因此我们去他的父类 QAbstractButton 中继续查找关键字 signals

这里的 clicked() 就是我们要找的信号。槽函数的寻找方式和信号一样,只不过它的关键字是 slot。


3、通过 Qt Creator 生成信号槽代码

Qt Creator 可以快速帮助我们生成信号槽相关的代码。

代码示例:在窗口中设置一个按钮,当点击 “按钮” 时关闭 “窗口”。


(1)新建项目,如下图为新建完成之后所包含的所有文件

注意:创建时要生成 UI 设计文件。


(2)双击 widget.ui 文件,进入 UI 设计界面


(3)在 UI 设计窗口中拖入一个 “按钮”,并且修改 “按钮” 的名称及字体大小等


(4)可视化生成槽函数

当鼠标单击 “转到槽...” 之后,出现如下界面:对于按钮来说,当点击时发送的信号是:clicked(),所以此处选择:clicked()

这个窗口列出了 QPushButton 给我们提供的所有信号(还包含了 QPushButton 父类的信号)。

对于普通按钮来说,使用 clicked 信号即可。
clicked(bool) 没有意义的,具有特殊状态的按钮(比如:复选按钮)才会用到 clicked(bool)。

(5)自动生成槽函数原型框架

A. 在 "widget.h" 头文件中自动添加槽函数的声明

说明:自动生成槽函数的名称有一定的规则,槽函数的命名规则为:on_XXX_SSS,其中:

  1. 以 "on" 开头,中间使用下划线连接起来。
  2. "XXX" 表示的是对象名(控件的 objectName 属性)。
  3. "SSS" 表示的是对应的信号

如:"on_pushButton_clicked() ",pushButton 代表的是对象名,clicked 是对应的信号。按照这种命名风格定义的槽函数,就会被 Qt 自动的和对应的信号进行连接。但是我们日常写代码的时候,除非是 IDE 自动生成,否则最好还是不要去依赖命名规则,而是显式使用 connect 更好

  • 一方面,显式 connect 可以更清晰直观的描述信号和槽的连接关系。
  • 另一方面,也是防止信号或者槽的名字拼写错误导致连接失效。

当然,是配置大于约定,还是约定大于配置,哪种更好。这样的话题业界尚存在争议,这里我个人还是更建议优先考虑显式 connect。


B. 在 "widget.cpp" 中自动生成槽函数定义  


(6)在槽函数函数定义中添加要实现的功能,实现关闭窗口的效果


三、自定义信号和槽

1、基本语法

在 Qt 中,允许自定义信号的发送方以及接收方,即可以自定义信号函数和槽函数。但是对于自定义的信号函数和槽函数有一定的书写规范。

Qt 中如果要让某个类能够使用信号槽(可以在类中定义信号和槽函数),则必须要在类最开始的地方写下 Q_OBJECT 宏(这个宏可以展开很多代码)。如果不加上这个宏,那么编译时就会报错。这个宏不需要我们自己手动添加,一般 Qt Creator 会帮我们自动生成。


(1)自定义信号函数书写规范

自定义信号在实际开发中很少需要用到,Qt 内置的信号就足以应付大部分的开发场景了。

所谓 Qt 的信号,本质上也就是一个 “函数”,在 Qt 5 以及更高版本中,槽函数和普通的成员函数之间没有什么差别。但是,信号是一类非常特殊的函数,我们只要写出函数声明,并告诉 Qt 这是一个 “信号” 即可。这个函数的定义是 Qt 在编译过程中自动生成的。

  1. 自定义信号函数必须写到 "signals" 下。
  2. 返回值为 void,只需要声明,不需要实现。
  3. 可以有参数,也可以发生重载

此处的 signals 是 Qt 自己扩展的关键字。qmake 构建 Qt 项目时,就会调用一些代码的分析 / 生成工具,扫描到类中包含 signals 这个关键字时,就会自动的把下面的函数声明认为是信号,并且给这些信号函数自动的生成函数定义。


(2)自定义槽函数书写规范

所谓的自定义一个槽函数,其操作规程和自定义一个普通成员函数没有什么区别。

  1. 早期的 Qt 版本要求槽函数必须写到 "public slots" 下,但是现在高级版本的 Qt 允许写到类的 "public" 作用域中或者全局下。
  2. 返回值为 void,需要声明,也需要实现。
  3. 可以有参数,可以发生重载。

槽声明的两种写法: 

此处的 slots 是 Qt 自己扩展的关键字,不是 C++ 标准中的语法。qmake 构建 Qt 项目时,就会调用专门的扫描器,扫描代码中特定的关键字(比如:slot),基于关键字自动生成一大堆相关代码。


(3)发送信号 

使用 "emit" 关键字发送信号 。"emit" 是一个空的宏。"emit" 其实是可选的,没有什么含义,只是为了提醒开发人员。


(4)示例

A. 一
a. 在 widget.h 中声明自定义的信号和槽


b. 在 widget.cpp 中实现槽函数,并且关联信号和槽

首先关联信号和槽,⼀旦检测到信号发射之后就会立刻执行关联的槽函数。反之,若先发射信号,此时还没有关联槽函数,当信号发射之后槽函数就不会响应。


B. 二 —— 当老师说 “上课了”,学生们就 “回到座位,开始学习”。

在源文件中新建两个类,一个是老师类,一个是学生类;首先选中项目名称,鼠标右键 ——> "add new...":

点击 "add new..." 之后,出现如下界面:

选择 "choose" 出现如下界面:

注意:在 Qt 中新建类时,要选择新建类的父类。

显然,当前项目中还没有什么类适合做新类的父类,同时新的类也不是一个 “窗口” 或者 “控件”,这种情况一般选择 QObject 作为基类。这样做的好处是这个新类的对象可以搭配 Qt 的对象树机制,便于对象的正确释放。

选择 “下一步”,出现如下界面:

对于 “学生类” 以上述同样的方式进行添加,添加完成之后,项目目录新增文件如下:

在 teacher.h 中声明信号函数:

在 student.h 中声明槽函数:

在 widget.h 中实例化 “老师类对象” 和 “学生类对象”:

在 student.cpp 中实现槽函数:

​​​​​​​

在 widget.cpp 中连接自定义信号和槽:​​​​​​​

运行结果如下图所示:


C. 三 —— 老师点击 “按钮” 触发学生上课

运行结果如下图所示:


2、带参数的信号和槽

Qt 的信号和槽也支持带有参数,同时也可以支持重载要求:信号函数的参数列表要和对应连接的槽函数参数列表一致。(一致主要是要求类型,个数如果不一致也可以,但要求信号的参数个数比槽的参数个数多)

此时信号触发,调用到槽函数的时候,信号函数中的实参就能够被传递到槽函数的形参当中。通过这样的机制就可以让信号给槽传递数据了。


(1)重载信号槽

A. ​​​​​​​在 "widget.h" 头文件中声明重载的信号函数以及重载的槽函数


B. 在 "Widget.cpp" 文件实现重载槽函数以及连接信号和槽

C. 执行结果


(2)信号槽参数列表匹配规则

A. 在 "widget.h" 头文件中声明信号和槽函数


B. 在 "widget.cpp" 文件中实现槽函数以及连接信号和槽

其实信号的参数个数可以多于槽函数的参数个数,但是槽的参数个数不能多于信号参数个数。但是实际开发中最好还是保持参数个数也能匹配⼀致。


(3)信号的参数个数多于槽函数的参数个数

A. 在 "widget.h" 头文件中声明信号和槽函数


B. 在 "widget.cpp" 文件中实现槽函数以及连接信号和槽


四、信号与槽的连接方式

1、一对一

主要有两种形式,分别是:

  1. ⼀个信号连接⼀个槽
  2. ⼀个信号连接⼀个信号

(1)一个信号连接一个槽

在 "widget.h" 中声明信号和槽以及信号发射函数:

在 "widget.cpp" 中实现槽函数,信号发射函数以及连接信号和槽:

​​​​​​​


(2)一个信号连接另一个信号

在上一段代码的基础上,在 "widget.cpp" 文件中添加如下代码:


2、一对多

一个信号连接多个槽:

在 "widget.h" 头文件中声明一个信号和三个槽:

在 "widget.cpp" 文件中实现槽函数以及连接信号和槽:


3、多对一

多个信号连接一个槽函数:

在 "widget.h" 头文件中声明两个信号以及一个槽:

在 "widget.cpp" 文件中实现槽函数以及连接信号和槽:


4、多对多

多个信号连接多个槽函数:

在 "widget.h" 头文件中声明三个信号以及三个槽:

在 "widget.cpp" 文件中实现槽函数以及连接信号和槽:

实际上,随着程序员经验越来越多,在 GUI 开发的过程中,“多对多” 其实是个 “伪需求”,实际开发很少会用到,绝大部分情况来说,“一对一” 就够用了。

信号槽存在的意义:

  • 解耦合(写代码追求 “高内聚,低耦合”)
  • 多对多(非常类似于 MySQL 中的 “多对多”)

五、信号和槽的其他说明

1、信号与槽的断开

使用 disconnect 即可完成断开,disconnect 的用法和 connect 基本一致。

实际上大部分情况下,把信号和槽连接上之后就不必管了,所以 disconnect 使用的比较少。主动断开往往是把信号重新绑定到另一个槽函数上。


2、Qt4 版本信号与槽的连接

Qt4 中的 connect 用法和 Qt5 相比更复杂,需要搭配 SIGNAL SLOT 宏来完成,而且缺少必要的函数类型的检查,使代码更容易出错。

在 "widget.h" 头文件中声明信号和槽:

​​​​​​​

在 "widget.cpp" 文件中实现槽函数以及连接信号与槽:


(1)Qt4 版本信号与槽连接的优缺点

  • 优点:参数直观。
  • 缺点:参数类型不做检测。


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

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

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

Lambda 表达式的语法格式如下:

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

说明:


(1)局部变量引入方式 [ ] ​​​​​​​

[ ] : 标识一个  Lambda 表达式的开始。不可省略。

说明:
  • 由于使用引用方式捕获对象会有局部变量释放了而 Lambda 函数还没有被调用的情况。如果执行 Lambda函数,那么引用传递方式捕获进来的局部变量的值不可预知。所以绝大多数场合使用的形式为:[=] () { }
  • 早期版本的 Qt,若要使用 Lambda 表达式,要在 ".pro" 文件中添加: CONFIG += C++11 因为 Lambda 表达式是 C++11 标准提出的。Qt5 以上的版本无需手动添加,在新建项目时会自动添加。

Lambda 表达式的使用:

以 [=] 方式传递,外部的所有变量在 Lambda 表达式中都可以使用:

以 [a] 方式传递,在 Lambda 表达式中只能使用传递进来的 a:

Lambda 表达式除了可以按照值得方式来捕获变量 [=],还可以按照引用得方式来捕获 [&](但 Qt 中很少这样写),捕获到的变量一般就是各自控件得指针。指针变量按照值传递或者引用来传递都无所谓。如果选择按照引用来传递,还得更关注这个引用得变量本身的生命周期。


(2)函数参数 ( )

(params) 表示 Lambda函数对象接收的参数,类似于函数定义中的小括号表示函数接收的参数类型和个数。参数可以通过按值(如:(int a,int b))和按引用(如:(int &a,int &b))两种方式进行传递。函数参数部分可以省略,省略后相当于无参的函数。

​​​​​​​


(3)选项 Opt

Opt 部分是可选项,最常用的是 mutable 声明,这部分可以省略。

Lambda 表达式外部的局部变量通过值传递进来时,其默认是 const,所以不能修改这个局部变量的拷贝,加上 mutable 就可以修改。


(4)Lambda 表达式的返回值类型 ->

可以指定 Lambda表达式返回值类型。如果不指定返回值类型,则编译器会根据代码实现为函数推导⼀个返回类型。如果没有返回值,则可忽略此部分。


(5)Lambda表达式的函数体 { }

Lambda 表达式的函数体部分与普通函数体一致。用 { } 标识函数的实现,不能省略,但函数体可以为空。


(6)槽函数使用 Lambda 表达式来实现

A. 点击按钮关闭窗口


B. 当 "connect" 函数第三个参数为 "this" 时,第四个参数使用 Lambda表达式时,可以省略掉 "this"


4、信号与槽的优缺点

(1)优点:松散耦合

信号发送者不需要知道发出的信号被哪个对象的槽函数接收,槽函数也不需要知道哪些信号关联了自己,Qt 的信号槽机制保证了信号与槽函数的调用。支持信号槽机制的类或者父类必须继承于 QObject 类。


(2)缺点:效率较低

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

⼀个客户端程序中,最慢的环节往往是 “人”。假设本身基于回调的方式是 10us,使用信号槽的方式是 100us。对于使用程序的人来说,是感知不到的。

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

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

相关文章

windows edge自带的pdf分割工具(功能)

WPS分割pdf得会员,要充值!网上一顿乱找,发现最简单,最好用,免费的还是回到Windows。 Windows上直接在edge浏览器打开PDF,点击 打印 按钮,页面下选择对应页数 打印机 选择 另存为PDF,然后保存就…

记录一下在Hyper-v中动态磁盘在Ubuntu中不完全用到的问题(扩展根目录)

在之前给hyper虚拟机的Ubuntu分配磁盘有20G; 后来在Ubuntu中查看磁盘发现有一个分区没用到: 贴的图片是完成扩展后的 之前这里是10G,然后有个dev/sda4的分区,也是10G,Type是Microsoft Basic Data; …

【LeetCode】填充每个节点的下一个右侧节点指针 II

目录 一、题目二、解法完整代码 一、题目 给定一个二叉树: struct Node { int val; Node *left; Node *right; Node *next; } 填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NUL…

spring security源码追踪理解(一)

一、前言 近期看了spring security相关的介绍,再加上项目所用若依框架的底层安全模块也是spring security,所以想从源码的角度加深下对该安全模块的理解(看源码之前,我们要先有个意识,那就是spring security安全模块主…

【面试题】Redo log和Undo log

Redo log 介绍Redo log之前我们需要了解一下,mysql数据操作的流程: 上述就是数据操作的流程图,可以发现sql语句并不是直接操作的磁盘而是通过操作内存,然后进行内存到磁盘的一个同步。这里我们必须要了解一些区域: 缓…

c++基础(类和对象中)(类的默认成员函数)

目录 一.构造函数(类似初始化) 1.概念 2.构造函数的特点 二.析构函数(类似 销毁对象/空间) 三.拷贝构造函数(类似复制粘贴的一种 初始化 ) 1.概念: 2.拷贝构造的特点: 四.赋值运算符重载&#xff08…

IDEA的工程与模块管理

《IDEA破解、配置、使用技巧与实战教程》系列文章目录 第一章 IDEA破解与HelloWorld的实战编写 第二章 IDEA的详细设置 第三章 IDEA的工程与模块管理 第四章 IDEA的常见代码模板的使用 第五章 IDEA中常用的快捷键 第六章 IDEA的断点调试(Debug) 第七章 …

STM32的ADC详解

目录 一、ADC简介 二、ADC的时钟 三、ADC特性 四、ADC功能说明 五、规则通道和注入通道 1.规则通道 2.注入通道 3.区别 六、数据寄存器 1.右对齐 2.左对齐 七、转换模式 1.单次转换模式 2.续转换模式 3.扫描模式 4.区别 八、程序实现 1.需求 2.ADC初始化 3.A…

ipv6 基础学习(一)

IPv6 为什么要有IPV6? IPv4地址空间有限:IPv4使用32位地址,最多可提供约43亿个地址。随着互联网设备数量的爆炸式增长,这些地址已经几乎耗尽。 IPv6地址空间庞大:IPv6使用128位地址,可以提供大约3.410^3…

爬虫自己做的

1.urllib 1.1基本使用 1.2 下载(图片,页面,视频) 1.3 get 1.3.1 quote 中文变成对应uncode编码 当url 的wd中文时 quote是将中文变成对应uncode编码 然后拼接成完整的url 1.3.2urlencode方法 wd有多个参数 1.3.3ajas get实例 …

【Git远程操作】理解分布式管理 | 创建远程仓库

目录 1.理解分布式管理 多人协作开发 2.创建远程仓库 2.1仓库名&路径 2.2初始化仓库&设置模板 1.理解分布式管理 目前我们学习的所有内容都是在本地来完成的。(add /commit /版本撤销回退/分支管理) Git是一个分布式 的版本控制系统。 分支…

动漫风格动漫404网站维护HTML源码

源码介绍 动漫风格动漫404网站维护HTML源码,源码由HTMLCSSJS组成,记事本打开源码文件可以进行内容文字之类的修改,双击html文件可以本地运行效果,也可以上传到服务器里面 效果预览 源码下载 动漫风格动漫404网站维护HTML源码

【存储学习笔记】1:机械硬盘(Hard Drive Disk)结构和寻址方式

目录 HDD的结构HDD的寻址方式CHS寻址(不适用于等密度结构磁盘)LBA寻址(目前普遍使用的线性寻址方式) HDD的寻址速度 HDD的结构 盘面(Platter):单面或者双面覆盖着用于记录数据的磁性物质&#x…

Gateway源码分析:路由Route、断言Predicate、Filter

文章目录 源码总流程图说明GateWayAutoConfigurationDispatcherHandlergetHandler()handleRequestWith()RouteToRequestUrlFilterReactiveLoadBalancerClientFilterNettyRoutingFilter 补充知识适配器模式 详细流程图 源码总流程图 在线总流程图 说明 Gateway的版本使用的是…

配置单区域OSPF

目录 引言 一、搭建基础网络 1.1 配置网络拓扑图如下 1.2 IP地址表 二、测试每个网段都能单独连通 2.1 PC0 ping通Router1所有接口 2.2 PC1 ping通Router1所有接口 2.3 PC2 ping通Router2所有接口 2.4 PC3 ping通Router2所有接口 2.5 PC4 ping通Router3所有接口 2.…

【Gitlab】记一次升级 Gitlab 后 API 失效的问题

背景 前段时间,因内部使用的 Gitlab 版本存在漏洞,需要进行升级,于是乎,将 Gitlab 从 16.6.0 升级到 16.11.3。而我们项目有个接口是用于获取 Gitlab 上的开发人员。 然后,今天,突然发现这个接口获取不到…

Linux网络——套接字与UdpServer

目录 一、socket 编程接口 1.1 sockaddr 结构 1.2 socket 常见API 二、封装 InetAddr 三、网络字节序 四、封装通用 UdpServer 服务端 4.1 整体框架 4.2 类的初始化 4.2.1 socket 4.2.2 bind 4.2.3 创建流式套接字 4.2.4 填充结构体 4.3 服务器的运行 4.3.1 rec…

在树莓派4B上部署yolov8环境完成高帧率检测任务

目录 前言 在树莓派上安装Pytorch 在树莓派上安装Ultralytics环境 在树莓派上初步测试模型 在树莓派上安装NCNN 用NCNN模型实现高帧率检测 前言 在我前面的文章里讲了如何用yolov8从0开始训练自己的模型,现在这篇文章将教大家如何在树莓派上部署yolov8的环境…

【BUG】已解决:TypeError: Descriptors cannot not be created directly.

已解决:TypeError: Descriptors cannot not be created directly. 目录 已解决:TypeError: Descriptors cannot not be created directly. 【常见模块错误】 【错误原因】 【解决方案】 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来…

适用于618/7xx芯片平台 AT开发 远程FOTA升级指南教程

简介 AT版本的远程升级主要是对AT固件版本进行升级,实际方式为通过合宙官方IOT平台升级或者使用自己搭建的服务器进行升级服务。 该文档教程流程适用于 618/716S/718P 芯片平台的Cat.1模块 合宙IOT平台配置 升级日志 —— 如何查看 升级日志 —— 响应码列表 响应…