在(一)QT学习中,我有提过信号和槽,并且说这个是QT的最有意思的地方,那么我们就先来看看这个机制是怎么样的吧
首先让我们新建一个项目,来看下信号和槽的用法。信号和槽是分开的,信号就是signal,槽是slot,在QT4中你可以非常直观的看到哪个是信号,哪个是槽,因为QT4是这样写的:
先定义下信号(不需要指定类型,默认就是public):
signals:
void signal_send_test();
再定义下槽(槽必须指定类型,可以是public protect private,一般常用public,因为方便其他类connect访问到):
public slots:
int slot_get_test();
QT4的connect:
connect(this,SIGNAL(signal_send_test()),this,SLOT(slot_get_test()));
connect(发送者,信号,接受者,槽),很简单,发送者就是谁发送信号,接受者就是谁接受并响应槽函数。我上面说非常直观就是因为SIGNAL和SLOT这两个宏,清晰的告诉你哪个是信号哪个是槽。
但是这种方式被QT5抛弃了(虽然QT5因为兼容问题,你还可以这样写,但是QT非常不推荐)。为啥呢?你可以看下SIGNAL和SLOT的定义,其实connect也可以看到:
bool connect(const QObject *, const char *,
const QObject *, const char *,
Qt::ConnectionType);
看到了么,信号和槽都是const char*,说明对connect函数来说,信号和槽就是两个字符类型,也就是SIGNAL和SLOT的作用就是把你传入的函数名转成字符类型。
既然你是字符类型,编译器编译阶段啥也检测不到啊!!!!!!,你把槽函数和信号名写成花都没问题:
connect(this,SIGNAL(signal_send_test()),this,SLOT(slot_get()));
编译器根本检测不出来好么,对它来说这就是一堆意义不明的字符,和你定义的啥string xxxx没啥区别。你把信号名写错没啥,最多你点击没啥响应,不会发生任何事。但是你敢把槽函数名写错试试,运行以后分分钟崩溃给你看!
(网上一堆文章解释原理,但是我还是忍不住。。。初学者特别容易犯,你复制粘贴函数名不好么,自己敲啥呢!!特别是你代码量一多,代码走读,十个人都看不出来你少个t。。。)
吐槽完QT4,我们来看下QT5推荐的写法:
connect(this,&MainWindow::signal_send_test,this,&MainWindow::slot_get_test);
这个就很灵性了,他要求传入的是函数指针,也就是指向函数对象的指针。既然是指针,你函数名给我错一个试试!!!
在QT的定义中是这样写的,我觉得可以帮助你理解:
static QMetaObject::Connection connect(const QObject *sender, const QMetaMethod &signal,
const QObject *receiver, const QMetaMethod &method,
Qt::ConnectionType type = Qt::AutoConnection);
所以总结下信号和槽的用法:
1.定义信号和槽:
signals:
void signal_send_test();
public slots:
int slot_get_test();
2.建立连接函数(.cpp文件中,需要的时候建立,或者直接在构造函数中建立):
connect(this,&MainWindow::signal_send_test,this,&MainWindow::slot_get_test);
3.发送信号:
emit signal_send_test();
然后下面你就不用管了,QT的元对象系统就好了,你专注你的槽函数就行
那让我们尝试下:
拖个button和label过来,点击button,让label显示文字
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(this,&MainWindow::signal_send_test,this,&MainWindow::slot_get_test);
}
MainWindow::~MainWindow()
{
delete ui;
}
int MainWindow::slot_get_test()
{
ui->label->setText(QString("hello, i'm QT"));
return 0;
}
void MainWindow::on_pushButton_clicked()
{
emit signal_send_test();
}
点击下按钮,就变成这样: