【Qt】7.信号和槽_connect函数用法(2)
文章目录
- 3. 信号和槽的使用
- 3.2 查看内置信号和槽
- 3.3 通过 Qt Creator 生成信号槽代码
- 3.4 第二种创建槽函数的方式
3. 信号和槽的使用
3.2 查看内置信号和槽
两个问题:
咋知道的
QPushButton
有个clicked
信号?咋知道的
QWidget
有一个close
槽?
Qt
里到底都提供了哪些内置的信号和槽可以让我们直接使用呢?大家在翻阅文档的时候,如果在当前类中没有找到对应的线索,不妨看看这个类的父类。
系统自带的信号和槽通常是通过 “
Qt 帮助文档
” 来查询。如上述示例,要查询 “按钮” 的信号,在帮助文档中输入:
QPushButton
,
- 首先可以在 “
Contents
” 中寻找关键字signals
,- 如果没有找到, 继续去父类中查找. 因此我们去他的父类
QAbstractButton
中继续查找关键字signals
这里的 clicked()
就是要找的信号。这里的参数checked
暂时用不到,后面遇到了再说。
槽函数的寻找方式和信号一样,只不过它的关键字是 slot
。
connect
的具体用法:
bool connect(const QObject *sender, const char *signal_, const QObject *receiver, const char *method, Qt::ConnectionType type = Qt::AutoConnection);
我们可以看到第2,4个参数类型都是char*
。
connect(button,&QPushButton::clicked,this,&Widget::close);
但是这里的第2,4个参数类型是void(*)()
,是函数指针,但是函数指针有很多种。
C++中,不允许你使用两个不同的指针类型,相互赋值,(函数传参,本质上就是赋值)
void(*)()
bool(*)()
即使是这两个函数指针的类型都是不一致的!!
这个函数声明,是以前l日版本的Qt的connect函数的声明,以前版本中,传参的写法和现在其实也是有区别的。
此时,给信号参数传参,要搭配一个SIGNAL
宏。
给槽参数传参,搭配一个SLOT
宏。
SIGNAL
宏和SLOT
宏会将传入的函数指针转成char*
connect(button,SIGNAL(&QPushButton::clicked),this,SLOT(&Widget::close);
Qt5
开始,对上述写法做出了简化。不再需要写SIGNAL
和SLOT宏了。
给connect
提供了重载版本,重载版本中,第二个参数和第四个参数成了泛型参数,允许咱们传入任意类型的函数指针了。
也就是CPP
泛型编程
此时connect
函数就带有了一定的参数检查功能。
如果你传入的第一个参数和第二个参数不匹配,或者第三个参数和第四个参数不匹配(不匹配指的是:2,4参数的函数指针,不是1,3参数的成员函数)
此时代码编译出错。
3.3 通过 Qt Creator 生成信号槽代码
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();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->setText("按钮");button->move(100,100);connect(button,&QPushButton::clicked,this,&Widget::handleClicked);
}Widget::~Widget()
{delete ui;
}void Widget::handleClicked()
{//按下按钮,修改窗口标题this->setWindowTitle("按钮已经按下");
}
运行:
点击
3.4 第二种创建槽函数的方式
先新建项目,点击.ui
控件
将Push Button
按钮拖到页面
右键按钮,点击转到槽
这个窗口就列出了QPushButton
给我们提供的所有的信号(还包含了QPushButton
父类的信号)
对于普通按钮来说, 使用 clicked
信号即可。 clicked(bool)
没有意义的,具有特殊状态的按钮(比如复选按钮)才会用到 clicked(bool)
。
双击clicked
,就会自动生成一个函数并跳转,并且声明也有
运行,点击
可以发现这里没有connect
,并且在对应的ui_widget
文件里面也没有。
在Qt
中,除了通过connect
来连接信号槽之外,还可以通过函数名字的方式来自动连接。
说明:
自动生成槽函数的名称有一定的规则。槽函数的命名规则为:
on_XXX_SSS
,其中:
以 "
on
" 开头,中间使用下划线连接起来;"
XXX
" 表示的是对象名(控件的objectName
属性)。"
SSS
" 表示的是对应的信号。如:"
on_pushButton_clicked()
" ,pushButton
代表的是对象名,clicked
是对应的信号。
按照这种命名风格定义的槽函数,就会被
Qt
自动的和对应的信号进行连接。但是咱们日常写代码的时候,除非是
IDE
自动生成,否则最好还是不要依赖命名规则,而是显式使用connect
更好。一方面显式
connect
可以更清晰直观的描述信号和槽的连接关系,另一方面也防止信号或者槽的名字拼写错误导致连接失效。
当函数名符合上述规则之后,Qt
就能自动的把信号和槽给建立上联系。
如果我们把on_pushButton_clicked
改成on_pushButton_click
,那么运行后点击按钮无反应,没有连接槽,并且出现下面提示,因为后者不存在Qt中。
Qt
中调用这个函数的时候,就会触发上述自动连接信号槽的规则
正是在自动生成的ui_widget.h
中调用的。
如果我们通过图形化界面创建控件,还是推荐使用这种快速的方式来连接信号槽
如果我们是通过代码的方式来创建控件,还是得手动connect
。(代码中没有调用connectSlotsByName
)