首先看下信号和槽的连接函数
QObject::connect(const QObject *sender, const char *signal,
const QObject *receiver, const char *method,
Qt::ConnectionType type = Qt::AutoCompatConnection)
这是我们最常用的形式。connect() 一般会使用前面四个参数,第一个是发出信号的对象,第二个是发送对象发出的信号,第三个是接收信号的对象,第四个是接收对象在接收到信号之后所需要调用的函数。也就是说,当 sender 发出了 signal 信号之后,会自动调用 receiver 的 slot 函数。
其中最后一个参数是枚举类型定义了三种信号和槽的连接方式:
(1) Qt::DirectConnection :信号发送后立即传递给相关联的槽函数,只有槽函数执行完毕返回后,发送信号"emit <信号>" 之后的代码才被执行
(2) Qt::QueuedConnection : 信号发送后排队,知道事件循环(event)有能力将它传递给槽; 而不管槽函数有没有执行,发送信号"emit <信号>" 之后的代码都会立即得到执行
(3) Qt::AutoConnection : 如果信号和槽函数在同一线程, 信号发出后,槽函数将立即执行, 等于Qt::DirectConnection; 如果信号和槽不在同一个线程,信号将排队,等待事件循环的处理,效果等同于Qt::QueuedConnection
一个类想支持信号和槽必须从QObject或QObject的子类继承。Qt信号和槽机制不支持对模板的使用
这两个东西说起来有点抽象,我还是不太明白;其实只要切实的去用过之后就会有一定的了解。
//connect() 第五个参数的作用, 连接方式: 默认,队列 ,直接
//多线程才有用
//默认的时候
//多线程,默认使用队列
//单线程,默认使用直接方式
//队列:槽函数所在的线程和接收者一样(同类)
//直接:槽函数所在线程和发送者一样(同类)
整理下Qt4和Qt5的信号和槽的连接方式
Qt4:
槽函数必须有 slots 关键字来修饰
SIGNAL SLOT将函数名字转换为字符串 不进行错误检查
connect(&w, SIGNAL(mySignal(int,QString)), this, SLOT(dealSlot(int,QString)));
Qt5:
(1) 自定义槽, 普通函数的用法
(2). 任意的成员函数,普通全局函数,静态函数
(3). 由于信号都是没有返回值,所以,槽函数一定没有返回值
connect(&button, &QPushButton::pressed, this, &MainWidget::close);//连接信号和槽
/* &button:信号发出者,指针类型
* &QPushButton::pressed:处理的信号, &发送者的类名::信号名字
* &MainWidget::close: 槽函数, 信号处理函数 &接收的类名::槽函数名字
*/
源码下载:https://download.csdn.net/download/dianzishi123/10825578
在同一个类中定义一个私有槽函数和一个信号,这个信号只是在头文件(.h文件)中声明并没有真正的去实现这个信号;同样的在头文件中声明一个私有槽函数,在源文件(.cpp文件)中去实现这个槽函数某个功能,在一定条件下发射未实现的私有信号去触发这个槽函数也是可以得;总的来说就是只要声明一个信号就可以用来发射触发槽。
工程目录:
启动程序看下效果:
点击下按钮Button后效果:
工程中的相关文件
1. slotTest.pro文件:分别管理的是头文件(.h文件),源文件(.cpp文件)和相应的QT库
SOURCES += \
main.cpp \
MyWidget.cpp
HEADERS += \
MyWidget.h
QT += widgets gui
2. main.cpp文件: 主要是QT的事件循环和显示一个widget
#include
#include "MyWidget.h"
int main(int argc, char** argv)
{
QApplication app(argc,argv);
MyWidget s;
s.show();
return app.exec();//qt事件循环
}
3.MyWidget.cpp文件: 槽函数的实现, 构造函数中信号和槽的连接; 设置控件布局显示
整个过程是这样的:按下Button按钮后会有一个按钮事件clicked的信号产生,去触发这个点击事件的槽函数; 在这个槽函数会打印"button ......"信息并发射我自己声明的信号"mySignals"然后这个信号又会触发另一个槽函数,在这个槽函数中打印信息"mySignals......."
#include "MyWidget.h"
#include
#include
#include
MyWidget::MyWidget(QWidget *parent) : QWidget(parent)
{
QHBoxLayout *hlay = new QHBoxLayout;
button = new QPushButton(this);
button->setText("Button");
lineEdit = new QLineEdit(this);
hlay->addStretch(10);//加个弹簧
hlay->addWidget(lineEdit);
hlay->addWidget(button);
hlay->addStretch(10);
QVBoxLayout *vlay = new QVBoxLayout;
vlay->addLayout(hlay);
this->setLayout(vlay);//this指当前类也就是MyWidget类 把这个布局用到这个界面中
//button 连接信号和槽
connect(this->button,SIGNAL(clicked()),this,SLOT(mySlotButtonCliced()),Qt::AutoConnection);
//自己定义的信号连接槽
connect(this,SIGNAL(mySignals()),this,SLOT(mySlot()),Qt::AutoConnection);//因为信号和槽都是本类中的,直接用this
}
//button 关联的槽函数
void MyWidget::mySlotButtonCliced()
{
qDebug()<<"button ...........";
emit mySignals();
}
//自己定义信号mySignals关联的槽函数
void MyWidget::mySlot()
{
qDebug()<<"mySignals..........";
}
4. MyWidget.h文件: 实现槽和信号的声明,和一些变量声明
#ifndef MYWIDGET_H
#define MYWIDGET_H
#include
#include
#include
class MyWidget : public QWidget
{
Q_OBJECT
public:
explicit MyWidget(QWidget *parent = nullptr);
signals://信号的声明不区分public和private
void mySignals();
private slots:
void mySlotButtonCliced();
void mySlot();
private:
QPushButton *button;
QLineEdit *lineEdit;
public slots:
};
#endif // MYWIDGET_H
在声明信号时, 添加有参数的信号, 在通过emit发射信号时把相应的参数传递给信号, 相关联的槽函数也有相同的参数,这样就把信号的参数,传递给槽函数了....................................................还未完....................
总结思考:
1. 私有的槽和信号是否只能在本类中使用;
2. 公有槽和信号是否可以实现不同类之间的通信
3. 感觉好灵活...