当前位置: 首页 > news >正文

【Qt】信号、槽

目录

一、信号和槽的基本概念

二、connect函数:关联信号和槽

例子:

三、自定义信号和槽

1.自定义槽函数

2.自定义信号函数

例子:

四、带参的信号和槽

例子:

五、Q_OBJECT宏

六、断开信号和槽的连接

例子:

七、lambda作为槽函数

例子:

qt中关于lambda引用传递捕捉


一、信号和槽的基本概念

1.信号

信号(signal)是由于用户对窗口或控件进行某些操作,导致窗口或控件产生某种特定事件,这时窗口类/控件类会发出信号给接收信号的控件对象。

2.槽

槽(slot)是对信号响应的函数。槽就是一个函数,与一般C++函数一样,可以定义在类任何访问权限下(public、protected、private),可以带参,可以重载,但是不能有默认参数。槽函数与普通函数不同的点是:槽函数可以关联某个信号,当该信号发出时关联的槽函数会自动执行。

信号和槽要解决的问题就是响应用户的操作

下面有一个例子:我们在窗口中创建一个按钮,点击该按钮控件该按钮上的内容会在"hello world

"和"hello qt"中间切换。

使用拖拽控件的方式构建图形界面:

当使用拖拽控件的方式构建图形界面时,每个控件对象都有下图中右下角中红圈圈的部分:objectName这个里面的内容就是通过拖拽创建的控件对象的名字,可以对该名字进行修改。

在Qt中,QObject类提供了一个静态成员函数connect,该函数用于关联信号函数和槽函数。

值得注意的是:如果使用这种拖拽方式构建图形界面,此时创建的控件对象都会在Widget类中的成员变量ui所指向的类中,因此在Widget类中访问以拖拽方式创建的控件对象时,要使用ui指针访问。

使用纯代码方式构建图形界面:

 值得注意的是:如果按照纯代码方式进行构建,那么我们应该将按钮控件对象声明为Widget类的成员变量,然后再Widget的构造函数中定义,这样就可以在槽函数中对该按钮对象进行操作。 

qt中类的关系:

QObject是Qt内置的父类,Qt中大多数类都是间接或直接继承自QObject。比如QWidget就是继承自QObject因此继承自QObject的类都可以使用QObject中的静态成员函数connect以及QObject的其他成员函数。

二、connect函数:关联信号和槽

例子:

现在写一个qt项目:通过点击窗体控件中的一个按钮控件使窗体控件关闭。

如下:发送信号的控件对象是button按钮,信号函数是QPushButton::clicked,接收信号的控件是窗口Widget,槽函数是Widget::close,close函数其实是QWidget类的成员函数,由于类Widget继承自QWidget因此Widget可以使用QWidget中的所有方法。

需要注意的是:使用connect函数关联信号和槽时,信号函数必须是发送信号的控件对象的成员函数;槽函数必须是接收信号的控件对象的成员函数。

通过图标判断信号函数和槽函数:

 像信号发射的图标是信号函数,比如这个clicked函数;像锯齿形的是槽函数,比如这个click。

三、自定义信号和槽

qt内部已经有大量现成的信号函数和槽函数,但是有些时候需要我们自己定义信号函数和槽函数。

1.自定义槽函数

1.自定义槽函数的返回值是void,需要声明和实现

2.可以有参数,可以被重载。

3.可以在public slots、protected slots、priavte slots下,也允许写在public下声明。

C++纯代码(即使用connect函数)方式连接信号和槽。

上面已有这种方式实现的代码。

UI设计窗口的方式自动连接信号和槽。

1.选中拖拽的控件点击右键,点击转到槽

2.选择要连接的信号

3.qt会自动生成一个函数,通过该函数的名字自动连接信号和槽

qt自动生成的这个函数名是具有格式规则的。对于函数名on_pushButton_clicked,on_后面就是发出信号的控件对象名字,clicked就是该控件发送的信号函数(一旦用户触发pushButton对象中的QPushButton::clicked,pushButton就会发送信号)。处理信号的动作就是在这个on_pushButton_clicked函数里实现。

2.自定义信号函数

1.自定义信号函数的返回值是void,只需声明,不需要定义,qt会自动帮我们完成定义。

2.可以有参数,可以被重载。

3.必须在signals后声明。

例子:

我们通过自定义信号完成一个简单的需求:但我们点击按钮控件后,窗口标题需要发生改变。


这有个emit其实是可以不写的。

四、带参的信号和槽

对于不带参的信号和槽前面已经有了。

1.信号函数和槽函数的参数类型必须一致,个数可以不一致(信号函数的参数个数多于槽函数)。

2.发射信号的时候,就可以给信号函数传递参数,该信号函数被执行完成后,会将这个参数传递给对应的槽函数。

例子:

实现一个功能:通过UI设计窗口创建两个按钮控件pushButton_1和pushButton_2。点击pushButton_1后窗口标题变为"标题一",点击pushButton_2窗口标题变为"标题二"。如下:

如果信号和槽连接,允许两者的参数个数可以不一致(信号函数的参数个数多于槽函数),但参数类型必须一致,这样的设计相较于参数数量必须一致的好处是什么?

情况:一个槽可能连接多个信号,如果要求参数必须一致才可连接,信号绑定槽的要求就会变高,如果一个槽的参数个数是1,那么参数个数是2的信号就无法绑定槽,尽管此时信号的第一个参数类型和这个槽的参数类型相同,也无法进行连接,这就导致了信号和槽之间的连接不够灵活。

五、Q_OBJECT宏

Qt中如果要让某个类可以使用信号和槽(可以在这个类中定义信号函数和槽函数),则必须要在这个类的最开始加上Q_OBJECT。

qt创建项目后会自动qt会自动帮我们加上了这个宏,如果没加这个宏使用了信号槽则会编译出错。

六、断开信号和槽的连接

使用disconnect断开信号和槽的连接,disconnect和connect在接口上的用法基本一致。断开信号和槽的连接比较少见,调用disconnect一般是为了更换一个信号连接的槽函数,disconnect后这个信号就可以连接其他新的槽函数了。

注意:

qt中的信号和槽中支持一个信号绑定多个槽一个槽被多个信号绑定

例子:

现在要设计这样一个功能:在UI窗口设计中创建按钮pushButton和pushButton_1,点击pushButton后将窗口标题改为"这是旧窗口标题",点击pushButton_1后,然后每次点击pushButton窗口标题变为”这是新窗口标题“。如下:

 

七、lambda作为槽函数

例子:

这个例子中lambda通过值传递捕捉了外层作用与的所有变量。

qt中关于lambda引用传递捕捉

在使用lambda表达式时要注意捕捉到的变量的生命周期,如果捕获了一个指针,该指针指向的空间在lambda访问的时候已经被释放,那么就会出现访问错误。

如果上面的例子中的lambda采用引用传递捕捉会出现什么情况?

当按钮button被点击,发送信号,则槽函数即lambda表达式会被执行,此时无法执行button->move(100,100)及以下代码。

原因:由于button(是一个指针变量,存的是地址)是一个栈区的变量,Widget的构造函数调用完后,button变量会被销毁,因此如果槽函数被触发执行,捕捉的是button的引用,想一下button变量都销毁了,那这个捕捉的引用也就指向垃圾空间了,但是如果button是Widget类的成员变量那么就不会出现错误。

Qt 5及更高版本的,都会默认在qt项目文件中.pro文件中加上CONFIG += c++11,但是Qt 5以下的版本则不会默认加,加上后就可以按照C++11来编译了。


http://www.mrgr.cn/news/80102.html

相关文章:

  • 【考前预习】3.计算机网络—数据链路层
  • 【Unity踩坑】Unity生成iOS的XCode项目时提示错误:xcrun: error: SDK “iphoneos“ cannot be located
  • SNN学习(3):Brain2Loihi,基于brain2实现的Loihi模拟器
  • 素数对
  • C语言:main函数
  • Docker操作及技巧
  • ESP32-S3模组上跑通ES8388(30)
  • C++3--内联函数、auto
  • virtualbox 搭建ubuntu
  • ---mysql server: Ubuntu Linux下最最基本的操作
  • 关于睡懒觉
  • Elasticsearch 集群部署
  • Stable Diffusion Controlnet常用控制类型解析与实战课程 4
  • RabbitMQ中的Work Queues模式
  • 使用Nexus3搭建npm私有仓库
  • 八大排序算法C语言版
  • 112.【C语言】数据结构之排序(详解插入排序)
  • 在 Ubuntu 24.04.1 LTS (WSL) 中使用 openssl 生成 keybox.xml
  • 进程保活机制
  • 深度学习中的多通道卷积与偏置过程详解
  • 零知识证明:区块链隐私保护的变革力量
  • 基于wifipumpkin3的AP伪造
  • Visual Studio 2022+CMake配置PCL1.14.1
  • vite打包失败 - out of memory
  • Vue.js 中,前端如何处理从后端返回的 Excel 文件流
  • vue3+setup使用rtsp视频流实现实时监控,全屏,拍摄,自动拍摄等功能(纯前端)