lambda qt 参数 槽函数_Qt信号与槽的使用

本文通过四个实例详细介绍了Qt信号与槽的使用,包括标准信号处理、自定义信号(带参数和不带参数)以及使用lambda表达式处理信号。通过这些例子,展示了如何连接信号和槽,以及如何在不同场景下使用lambda表达式来处理信号,加深了对Qt编程的理解。
摘要由CSDN通过智能技术生成

1  新建工程

先创建一个控件基础工程,创建后的界面如下:

cf0d8774191e38a1fb767f4218cc7117.png

主函数我们不需要修改,就保持这样,对于C++的知识我不太理解。

上述代码中,执行到第7行的时候,会先去执行基类的构造函数,再执行MyWidget类的构造函数。我们只需要在构造函数中实现需要实现的功能。

构造函数对应在mywidget.cpp中:

27c18f5e14f531df9402fb3cdc80fb18.png

2  测试代码

实例一:标准的信号处理

测试目的:在主窗口中,新建两个按钮,功能如下:

按钮一的功能:按下按钮,关闭主窗口;

按钮二的功能:释放按钮,更改按钮二的文本,并隐藏按钮一。

由于在实现过程中,会用到信号与槽的知识,就先简单介绍一下基本知识,可能不正确,这只是我个人的理解:

信号:某一事件发生时产生,用于表示一个事件发生了。

槽:就是信号处理函数,用于指示当信号发生时,需要做出什么动作。

其中,我们connect函数来连接信号与槽之间的关系,函数的原型如下:

connect(const QObject *sender, const QMetaMethod &signal, const QObject *receiver, const QMetaMethod &method, Qt::ConnectionType type = Qt::AutoConnection);

举例说明:

connect(&b1, &QPushButton::pressed, this, &MyWidget::close);

/* &b1:信号发出者,指针类型

* &QPushButton::pressed:处理的信号,&发送者的类名::信号名字

* this:信号接收者

* &MyWidget::close:槽函数,信号处理函数 &接收的类名::槽函数名字

*/

不同的控件有哪些信号,可通过帮助文档查看,以QPushButton为例进行说明(点QPushButton,再按F1):

b8256847abf522901801d026cf5a3ed8.png这里没有看到signal函数,可能是从它的父类继承过来的,我们再看一下它的父类:

c3159144f324122f53d7475db1ebe73d.png

14f6e0051e2cd591c9e2ae3bf2d3bac7.png

eda784cff38fb1e4a59e33f6be7f1574.png

实现的相关代码

先在MyWidget类中实现两个按钮(mywidget.h):

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 #ifndef MYWIDGET_H2 #define MYWIDGET_H

3

4 #include

5 #include

6

7 class MyWidget : publicQWidget8 {9 Q_OBJECT10

11 public:12 MyWidget(QWidget *parent = 0);13 ~MyWidget();14

15 private:16 QPushButton b1;17 QPushButton *b2;18

19 voidmyslot();20

21 };22

23 #endif //MYWIDGET_H

View Code

再在构造函数中实现两个按钮的功能(mywidget.cpp):

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 #include "mywidget.h"

2 #include

3

4 MyWidget::MyWidget(QWidget *parent)5 : QWidget(parent)6 {7 b1.setParent(this);8 b1.setText("按钮一");9 b1.move(100, 100);10

11 b2 = new QPushButton(this);12 b2->setText("按钮二");13

14 connect(&b1, &QPushButton::pressed, this, &MyWidget::close);15 /*&b1:信号发出者,指针类型16 * &QPushButton::pressed:处理的信号,&发送者的类名::信号名字17 * this:信号接收者18 * &MyWidget::close:槽函数,信号处理函数 &接收的类名::槽函数名字19 */

20

21 /*

22 * 自定义槽,普通函数的用法23 * Qt5:任意的成员函数,普通全局函数,静态函数24 * 槽函数需要和信号一致(参数、返回值)25 * 由于信号都是没有返回值,所以槽函数一定没有返回值26 */

27 connect(b2, &QPushButton::released, this, &MyWidget::myslot);28

29 connect(b2, &QPushButton::released, &b1, &MyWidget::hide);30 /*

31 * 信号:短信32 * 槽函数:接收短信的手机33 */

34 }35

36 voidMyWidget::myslot()37 {38 b2->setText("123");39 }40

41 MyWidget::~MyWidget()42 {43

44 }

View Code

运行,进行测试:

6ad4bd8d7bb6278c4e7d9a9739f0091d.png

实例二:自定义不带参数信号处理

目的:实现两个窗口,主窗口和子窗口,并且每个窗口都有一个按键,按键功能如下:

主窗口按键的功能:显示子窗口,关闭父窗口;

子窗口按键的功能:关闭子窗口,显示父窗口。

主窗口和子窗口的切换显示全部由主窗口控制,可以理解为:主窗口的权限大于子窗口,子窗口的按键按下去只是产生一个信号,主窗口再对信号进行处理。

1afa4f81c5f471afc9abfbe62d196ebe.png

新建一个工程,工程创建之后,有以下文件,其中,subwindown相关文件是通过点击signal_slot_2目录文件,选择添加新文件,选择C++ --> C++ Class,基类我们选择QWidget:

e6b60c48aa0161583b5d796fc3325e5c.png

693cd2575f04fc1fb4bc5857fb7f85d8.png

623dac6aeeee83ca317ddadb0c6d0c67.png

实现的代码如下:

widget.h是widget类所在同文件,主要实现:声明主窗口按键处理函数、声明子窗口信号接收处理函数、实例化一个subwindown类对象、实例化一个QPushButton类对象。

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 #ifndef WIDGET_H2 #define WIDGET_H

3

4 #include

5 #include

6 #include "subwindown.h"

7

8 class Widget : publicQWidget9 {10 Q_OBJECT11

12 public:13 Widget(QWidget *parent = 0);14 ~Widget();15

16 voidmy_slot();17 voiddealsub();18

19 private:20 QPushButton b_main;21

22 subwindown sw;23 };24

25 #endif //WIDGET_H

View Code

subwindown.h是subwindown类所在头文件,主要实现:声明子窗口按键处理函数、声明一个信号、实例化一个QPushButton类对象。

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 #ifndef SUBWINDOWN_H2 #define SUBWINDOWN_H

3

4 #include

5 #include

6

7 class subwindown : publicQWidget8 {9 Q_OBJECT10 public:11 explicit subwindown(QWidget *parent =nullptr);12 //定义槽函数

13 voidsendslot();14

15 signals:16 /*

17 * 信号必须有signals关键字声明18 * 信号没有返回值,但可以有参数19 * 信号就是函数的声明,只需声明,无需定义20 * 使用:emit mysignal();21 */

22 voidmysignal();23

24 publicslots:25

26 private:27 QPushButton b_sub;28

29 };30

31 #endif //SUBWINDOWN_H

View Code

main.cpp中的代码不改动,就使用生成的代码:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 #include "widget.h"

2 #include

3

4 int main(int argc, char *argv[])5 {6 QApplication a(argc, argv);7 Widget w;8 w.show();9

10 returna.exec();11 }

View Code

widget.cpp中实现的是主窗口的构造函数,主要实现:接收主窗口按键的信号并处理、接收子窗口发送的信号并处理。

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 #include "widget.h"

2

3 Widget::Widget(QWidget *parent)4 : QWidget(parent)5 {6 setWindowTitle("主窗口");7

8 //设置按钮相关属性

9 b_main.setParent(this);10 b_main.setText("切换子窗口");11 b_main.move(50, 50);12 //处理主窗口的按钮所产生的信号

13 connect(&b_main, &QPushButton::clicked, this, Widget::my_slot);14

15 //接收子窗口信号,并进行处理

16 connect(&sw, &subwindown::mysignal, this, &Widget::dealsub);17 resize(400, 300);18 }19

20 voidWidget::my_slot()21 {22 //显示子窗口

23 sw.show();24 //父窗口隐藏

25 this->hide();26 }27

28 voidWidget::dealsub()29 {30 //主窗口显示

31 this->show();32 //子窗口隐藏

33 sw.hide();34 }35

36 Widget::~Widget()37 {38

39 }

View Code

subwindown.cpp中实现的是子窗口的构造函数,主要实现:接收子进程按键的信号并处理,处理方式为发送一个自定义信号。

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 #include "subwindown.h"

2

3 subwindown::subwindown(QWidget *parent) : QWidget(parent)4 {5 setWindowTitle("子窗口");6

7 //按键属性设置

8 b_sub.setText("切换主窗口");9 b_sub.setParent(this);10 b_sub.move(50, 50);11

12 //接收按键信号并处理

13 connect(&b_sub, &QPushButton::clicked, this, &subwindown::sendslot);14 resize(400, 300);15 }16

17 voidsubwindown::sendslot()18 {19 //发送信号

20 emit mysignal();21 }

View Code

运行测试:

ed0aa9a101b54d96367a8b85d8a6a214.png点击“切换子窗口”按键:

02838443a22e76716a49aae772010906.png

实例三:自定义带参数信号处理

功能:在空白窗口中定义一个按钮,点击按钮发送一个自定义的带参数的信号,然后由本窗口接收信号并将参数打印出来。

首先,创建一个控件基类工程,创建后包含的文件如下:

26e4196bd1e04afa29504d9c96b53aed.png

在widget.h中,实现的功能有:声明一个发送信号函数、声明一个接收信号函数、自定义一个带参数的信号、实例化一个QPushButton对象。

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 #ifndef WIDGET_H2 #define WIDGET_H

3

4 #include

5 #include

6

7 class Widget : publicQWidget8 {9 Q_OBJECT10

11 public:12 Widget(QWidget *parent = 0);13 ~Widget();14

15 //点击按钮,发送信号函数

16 voidsend_signal();17 //接收信号处理函数

18 void recv_signal(int, QString);19

20 signals:21 //自定义一个带参数的信号

22 void mysignal(int, QString);23

24 private:25 QPushButton b_main;26

27 };28

29 #endif //WIDGET_H

View Code

在widget.cpp中,实现的功能有:接收点击按键的信号并进行处理,接收自定义的信号并进行处理。

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 #include "widget.h"

2 #include

3

4 Widget::Widget(QWidget *parent)5 : QWidget(parent)6 {7 b_main.setParent(this);8 b_main.setText("发送");9 b_main.move(100, 100);10

11 //点击按钮,发送信号

12 connect(&b_main, &QPushButton::clicked, this, &Widget::send_signal);13

14 //接收点击按钮,发送的信号

15 void (Widget::*testsignal)(int, QString) = &Widget::mysignal;16 connect(this, testsignal, this, &Widget::recv_signal);17

18 this->resize(300, 300);19 }20

21 voidWidget::send_signal()22 {23 emit mysignal(100, "我已经发送信号");24 }25

26 void Widget::recv_signal(inta, QString str)27 {28 qDebug() << a <

31 Widget::~Widget()32 {33

34 }

View Code

运行,并进行测试,点击一次发送按钮,就会发送一个自定义信号,并接收到了它:

d3ddfded639f6b2ef439cf59e9aac700.png

实例四:lambda表达式的使用

功能:创建一个按钮,点击按钮发送一个信号,不需要指定信号接收函数和信号接收者,直接使用匿名函数(lambda表达式)实现。

先新建一个工程,新建后的工程文件如下:

28dfd82dda1c5cadd2b6433606084322.png

由于lambda是C++11支持的特性,所以我们需要在lambda_test.pro文件末尾添加一句:CONFIG += C++11

先把代码放上,再说明lambda表达式的作用。

widget.h文件:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 #ifndef WIDGET_H2 #define WIDGET_H

3

4 #include

5 #include

6

7 class Widget : publicQWidget8 {9 Q_OBJECT10

11 public:12 Widget(QWidget *parent = 0);13 ~Widget();14

15 private:16 //定义一个类中成员变量

17 int a = 10;18

19 };20

21 #endif //WIDGET_H

View Code

widget.cpp文件:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 #include "widget.h"

2 #include

3

4 Widget::Widget(QWidget *parent)5 : QWidget(parent)6 {7 QPushButton *b_main = new QPushButton(this);8 b_main->setParent(this);9 b_main->setText("开始");10 b_main->move(100, 100);11

12 //定义一个外部局部变量

13 int b = 12;14 //Lambda表达式,匿名函数对象15 //C++11增加的新特性,项目文件: CONFIG += C++1116 //Qt配合信号一起使用,非常方便

17 connect(b_main, &QPushButton::clicked,18 //=:把外部所有局部变量、类中所有成员以值方式传进来19 //this:类中所有成员以值传递方式20 //&:引用符号,外部所有局部变量

21 [=](boolisCheck)mutable22 {23 b_main->setText("lambda表达式");24 qDebug() << "已经进入lambda表达式";25 qDebug() << a <

32 this->resize(300, 300);33 }34

35 Widget::~Widget()36 {37

38 }

View Code

下面就简单的说明lambda表达式的语法,我也不是很懂,根据测试结果进行说明。

格式:[capture](parameters) mutable ->return-type{statement};

capture:捕捉列表,也单独代表函数的开始,主要有以下使用方式:

单独传递外部变量,如:[b_main]

=:把外部所有局部变量、类中所有成员以值方式传进来(widget.c和widget.h文件中的成员)

this:类中所有成员以值传递方式(widget.h文件中的成员)

&:引用符号,外部所有局部变量(widget.c文件中的成员),当变量是指针时,最好别用这个。

parameters:参数列表,信号的参数。

mutable :值传递时,默认变量为只读的,如果需要在匿名函数中改变它,需要这个参数

运行代码进行测试:

33c2b519e61ef78515da392e4c85ef5d.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值