从零开始学Qt(四)信号与槽
扫描二维码
随时随地手机看文章
信号与槽
-----书不记,熟读可记;义不精,细思可精。
1、信号/槽是啥?
古有“烽火狼烟”传递消息,敌人来犯的消息迅速传达开来,是多么的聪慧啊。烟就是信号;下一个燃火台看到烟后就点燃燃料,这个就槽。换种方法说就是 一个按钮被点击了,会触发一个点击的信号;槽是指收到信号之后,具体要去做什么。
专业点说你可以从设计模式上理解,其实就是观察者模式。信号是“主题”,每个槽是“观察者”。当发出信号的时候,对该信号感兴趣的槽就会被触发(有没有觉得突然逼格变高了)。简单点说信号类似广播,每个槽都可以听到这个广播,但是只有你连接过的槽才会去接收这个信号,并作出相应的操作。
信号和槽分为两种,一种是类自带的信号和槽,直接可以使用。另外一种是我们可以自定义信号和槽,使得我们更加的自由。当一个类被继承的时,该类的信号和槽也同时被继承。
2、怎么查看Qt中具体类的信号和槽
有两种方法可以查看,第一种我们可以打开Qt Assistant(助手),还有一种是直接打开Qt Creator(里面也集成了上面那个模块),所以我们直接讲后者。跟着我的步骤,我们以查看QLabel为例子,如下图:
点击上图的信号/槽,就会跳到具体的位置。
3、打开之前的HelloQt工程
我们这篇的内容会围绕着这个例子来讲《从零开始学Qt(三)从Hello,Qt说起》。所以我们来打开之前的工程。并且介绍下,如何打开Qt工程。
打开Qt有两种方法:
1)第一种是打开工程目录,然后双击 HelloQt.pro 文件,就可以直接打开该工程。
2)先打开Qt Creator,从文件->打开文件或项目,找到HelloQt工程,然后选中HelloQt.pro文件,然后点击打开。
4、自定义信号跟槽
类声明中必须包含Q_OBJECT宏;信号跟槽都必须在头文件中定义。
1)信号: 只要再.h中声明即可,发射信号用emit关键字。
2)槽:实现的时候跟普通的成员函数一样实现即可。
5、格式
connect(发送者,信号,接收者,槽);
1)一个信号可以与另外一个信号相连
connect(发送者,信号,接收者,信号);
2)一个信号可以与多个槽相连
connect(发送者1,信号1, 接收者1, 槽1);
connect(发送者1, 信号1, 接收者2, 槽2);
3)一个槽可以被多个信号关联。
connect(发送者1,信号1, 接收者1, 槽1);
connect(发送者2, 信号2, 接收者1, 槽1);
6、例子
1)添加一个按钮,如图下图所示操作:
2)Ctrl + S 保存
3)点击回到编辑界面,如下图:
3)在.h里面自定义槽函数,响应按钮按下的信号
双击mainwindow.h;在编辑窗口看到mainwindow.h文件。如下图:
#ifndef MAINWINDOW_H #define MAINWINDOW_H #includenamespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); public slots: //所有的槽函数都必须申明public slots语句内 void slt_clearLabel(); //这里定义一个槽函数,来实现清空文本框的内容 private: Ui::MainWindow *ui; }; #endif // MAINWINDOW_H
4)实现槽函数
上面也提到了,实现槽函数。跟实现普通的成员函数一样。
void MainWindow::slt_clearLabel() { ui->label->clear(); //清空文本框内容 }
5)绑定
connect(ui->pushButton, SIGNAL(pressed()), this, SLOT(slt_clearLabel()));
6)mainwindow.cpp文件的完整代码
#include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); connect(ui->pushButton, SIGNAL(pressed()), this, SLOT(slt_clearLabel())); } MainWindow::~MainWindow() { delete ui; } void MainWindow::slt_clearLabel() { ui->label->clear(); //清空文本框内容 }
7)运行结果
点击按钮的时候,QLabel里面的文字会被清空。
7、Qt5中的新语法
这里先简单介绍一部分。介绍是因为Qt5里面更新的语法,有些比较实用。为什么先介绍上面的,是因为旧版本对于新手比较好理解。
1)先来一个比较。一个QSlider对象的valueChanged信号链接到一个QSpinBox对象的setValue槽,使用
传统方式:
connect(slider, SIGNAL(valueChanged(int)), spinbox, SLOT(setValue(int)));
使用新式语法格式:
connect(slider, &QSlider::valueChanged, spinbox, &QSpinBox::setValue);
2)新语法的优点
编译期:会检查信号和槽是否存在,且参数类型是否合法,如果错误将编译不通过。(旧版的如果参数不匹配只会有个Warning的信息,而编译可以通过) 信号可以和槽函数、普通函数、类的成员函数、lambda函数连接。(旧版的只能跟槽函数连接)允许一些自动类型转换,即信号和槽参数类型不必完全匹配。(旧版的一定要匹配,否则连接失败。槽函数无法响应)。例如:(旧版的会连接失败)connect(a, SIGNAL(sig(int)), b, SLOT(slt(double)));参数可以是typedef,如下:(旧版的会连接失败)
typedef int myInt; connect(a, SIGNAL(sig(int)), b, SLOT(slt(myInt)));
8、作业
你们可以试着,把例子里面的旧版连接,改成Qt5新语法的连接。(答案在下篇博客)
结束:
最后有同学会遇到问题,可以加QQ群讨论。如果我哪里错了,也希望有人告知我,我来修改文章,以免误导他人。