1.什么是信号槽
Qt使用信号与槽机制进行对象间的通信,当某个对象的状态发生变化时,该对象会触发一个信号,该信号和另外一些对象的槽函数绑定,信号的触发将导致执行这些槽函数,这些槽函数将处理第一个对象状态的变化,完成对象之间的通信。
2.信号(signal)
如何定义信号
使用关键词signals
请注意:信号不能是公共 (public)的或私有 (private)的。 Qt 信号是 protected 类方法。
signals:
void send();
如何使用信号
使用emit关键词
emit send()
槽(slot)
如何定义槽(两种方式)
1.使用关键字slots(可以是公有,私有或保护)
注意:私有槽函数无法被外部类使用。
private slots:
void get();
2.在UI设计器中跳转槽函数。
在UI界面跳转槽后,Qt会自动帮我们生成槽函数。默认私有。
注意:所有on_xxx_xxx的都会被Qt默认识别为槽函数,所以在声明函数请不要用on_开头。
3.信号槽如何使用
这是Qt官方示例文档上的定义。sender和receiver必须是继承QObject* 类型的。
注意:所有信号槽都是基于QObject(所有的窗口及事件等都是继承QObject)
在Qt4的信号槽连接方式为:
connect( 信号,SIGNAL(),槽,SLOT() );
Qt5的信号槽方式为:
static QMetaObject::Connection connect(const QObject *sender, const QMetaMethod &signal,
const QObject *receiver, const QMetaMethod &method,
Qt::ConnectionType type = Qt::AutoConnection);
connect(ui->pushButton,&QPushButton::clicked,this,&MainWindow::closeWindow);
注意:信号和槽函数要参数对应,Qt4需要带参数类型,Qt5则不需要。
示例:
mainwindow.h
//普通函数也可以作为槽函数。
public slots:
void get1();
public:
void get2(int a ,int b);
signals:
void send1();
void send2(int a ,int b);
mainwindow.cpp
connect(this,SIGNAL(send1()),this,SLOT(get1());//Qt4
connect(this,SIGNAL(send2(int,int),this,SLOT(get2(int,int);//Qt4
connect(this,&Mainwindow::send1,this,&Mainwindow::get1);//Qt5
connect(this,&Mainwindow::send2,this,&Mainwindow::get2);//Qt5
//槽也可以是信号,作为信号转发
connect(this,SIGNAL(send1()),this,SIGNAL(send2());//Qt4
connect(this,&Mainwindow::send1,this,&Mainwindow::send2);//Qt5
4.信号槽第五个参数(多线程)
1、Qt::AutoConnection: 默认值,使用这个值则连接类型会在信号发送时决定。如果接收者和发送者在同一个线程,则自动使用Qt::DirectConnection类型。如果接收者和发送者不在一个线程,则自动使用Qt::QueuedConnection类型。
2、Qt::DirectConnection:槽函数会在信号发送的时候直接被调用,槽函数和信号发送者在同一线程。效果看上去就像是直接在信号发送位置调用了槽函数,效果上看起来像函数调用,同步执行。
emit语句后面的代码将在与信号关联的所有槽函数执行完毕后才被执行。
无论槽函数所属对象在哪个线程,槽函数都在发射信号的线程内执行。
3、Qt::QueuedConnection:信号发出后,信号会暂时被放到一个消息队列中,需等到接收对象所属线程的事件循环取得控制权时才取得该信号,然后执行和信号关联的槽函数,这种方式既可以在同一线程内传递消息也可以跨线程操作。
emit语句后的代码将在发出信号后立即被执行,无需等待槽函数执行完毕
槽函数在接收者所依附线程执行。
4、Qt::BlockingQueuedConnection:槽函数的调用时机与Qt::QueuedConnection一致,不过发送完信号后发送者所在线程会阻塞,直到槽函数运行完。而且接收者和发送者绝对不能在一个线程,否则程序会死锁。在多线程间需要同步的场合可能需要这个。
5、Qt::UniqueConnection:这个flag可以通过按位或(|)与以上四个结合在一起使用。当这个flag设置时,当某个信号和槽已经连接时,再进行重复的连接就会失败。也就是为了避免重复连接。