Qt信号与槽

信号与槽

  • GUI用户界面中,当用户操作一个窗口部件时,需要其他窗口部件响应,传统方式经常使用callback(回调机制)来实现。所谓回调即事先将函数指针作为参数传递另一个函数,然后在函数处理过程中适当地方调用回调函数回调机制有两个缺陷:类型不安全,不能保证调用函数过程中使用正确的参数;强耦合,处理函数必须知道调用哪个回调函数。Qt的信号与槽机制是类型安全的,松耦合,更灵活,更方便。
  • 信号与槽(Signal & Slot)是 Qt 编程的基础,也是 Qt 的一大创新。因为有了信号与槽的编程机制,在 Qt 中处理界面各个组件的交互操作时变得更加直观和简单。
  • 信号(Signal)就是在特定情况下被发射的事件,例如PushButton 最常见的信号就是鼠标单击时发射的 clicked() 信号。发射信号使用Qt的emit关键字。QT 的 signals 关键字指出进入了信号声明区,随后即可声明自己的信号。

 
定义信号,如:

signals: 
	void launch(QString &str);	//声明一个信号, 信号不能具体实现

 
发射信号,如:

private slots: 
	void reception() {	//响应信号的槽函数
		QString str = "响应了 launch() 信号!";
		emit launch(str);	//发射信号
	}

 
槽(Slot)就是对信号响应的函数。槽就是一个函数,与一般的C++函数是一样的,可以声明在类的任何部分(public、private 或 protected),可以具有任何参数,也可以被直接调用。槽函数与一般的函数不同的是:槽函数可以与一个信号关联,当信号被发射时,关联的槽函数被自动执行。
 
声明三个槽方法,如:

private slots: 
	void reception();	//响应信号的槽函数
	void reception2();
	void accept(QString &str);

 
槽方法中处理需要处理的工作,如:

void MainWindow::accept(QString &str){	//MainWindow.cpp中实现槽方法
   	qDebug() << str;	//调试输出	添加头文件 #include 
}

 
GUI 程序设计的主要内容就是对界面上各组件的信号的响应,只需要知道什么情况下发射哪些信号,合理地去响应和处理这些信号就可以了。
 
信号与槽关联是用 QObject::connect() 函数实现:

QMetaObject::Connection QObject::connect(
	const QObject *sender, 			//信号发送者
	const char *signal, 			//发送的信号
	const QObject *receiver, 		//信号接收者
	const char *method, 			//表示与信号连接的方式的字符串,可以是槽或信号
	Qt::ConnectionType type = Qt::AutoConnection	//连接方式,默认自动连接
)

常用格式:connect(sender, SIGNAL(signal()), receiver, SLOT(slot()));

 
用来表示信号和槽的参数都是字符串,Qt提供了两个宏用于构造这样的字符串:对于信号使用SIGNAL,对于槽则使用SLOT,用它们将函数的原型包围起来即可。注意connect方法采用SIGNAL()及SLOT()时,这里的函数原型只能写出类型,不能有任何参数名,否则连接将会失败。
 
同时信号与槽连接方式:

序号 代码 连接方式
1) Qt::AutoConnection: (默认连接方式)自动方式,由系统自动选择连接方式。
2) Qt::DirectConnection: 直接方式,信号发射时,立即调用槽。
3) Qt::AutoConnection: 队列方式,信号发射时产生一个事件进入队列,事件被处理时槽才能调用。
4) Qt::BlockQueuedConnection: 阻塞队列方式,信号发射时产生一个事件进入队列,然后当前线程进入阻塞状态,直到事件处理完毕,若接收方位于发送信号的线程中,则程序会死锁,故此连接方式仅用于多线程。

信号可以看做是特殊的函数,需要带括号,可带参数,信号无需实现也不能实现。槽函数需要带括号,有参数时还需要指明参数。当信号和槽函数带有参数时,在 connect()函数里,要写明参数的类型。信号的参数需与槽的参数列表一致,允许比槽参数多。如果不匹配或参数过少,会出现编译错误或运行错误。在使用信号与槽的类中,必须在类的定义中加入宏 Q_OBJECT。当一个信号被发射时,与其关联的槽函数通常被立即执行,就像正常调用一个函数一样。只有当信号关联的所有槽函数执行完毕后,才会执行发射信号处后面的代码。
 
 

信号与槽的关联方式有如下特点:

1. 一个信号对应一个槽方法

在这里插入图片描述

signals:  		void launch(QString &str);  //声明信号
private slots:	void accept(QString &str);	//声明槽函数

//connect连接信号与槽
connect(this, SIGNAL(launch(QString&)), this, SLOT(accept(QString&)));

 

2. 一个信号对应一个信号

在这里插入图片描述

signals:  	void launch(QString &str);  //声明信号
signals:	void launch2();	//声明信号

//connect连接信号与信号
connect(this, SIGNAL(launch(QString&)), this, SIGNAL(launch2()));

 

3. 一个信号对应多个槽方法

Qt信号与槽_第1张图片

signals:  		void launch(QString &str);  //声明信号

private slots:  void reception();	//响应信号的槽函数
private slots:  void reception2();	//响应信号的槽函数
private slots:  void reception3();	//响应信号的槽函数

//connect连接信号与槽
connect(this, SIGNAL(launch(QString&)), this, SLOT(reception()));
connect(this, SIGNAL(launch(QString&)), this, SLOT(reception2()));
connect(this, SIGNAL(launch(QString&)), this, SLOT(reception3()));

 

4. 多个信号对应一个槽方法

Qt信号与槽_第2张图片

signals:  		void launch(QString &str);  //声明信号
signals:  		void launch2(); 			//声明信号
signals:  		void launch3();  			//声明信号

private slots:  void reception();	//响应信号的槽函数

//connect连接信号与槽
connect(this, SIGNAL(launch(QString&)), this, SLOT(reception()));
connect(this, SIGNAL(launch2()), this, SLOT(reception()));
connect(this, SIGNAL(launch3()), this, SLOT(reception()));

 
 

信号与槽的断开关联:

//元对象声明
QObject::disconnect(const QObject* sender,const char* signal, const QObject *receiver,const char* method);

 
1. 断开与一个对象所有的信号的所有关联

//断开sender对象与所有的信号连接
disconnect(sender,0,0,0);   

相当于:
sender->disconnect();

 
2. 断开与一个指定信号的所有关联

//断开了 single1() 信号 与所有响应的槽函数连接
disconnect(sender, SIGNAL(single1()),  0,  0); 

相当于:
sender->disconnect(SIGNAL(single1()));

 
3. 断开与一个指定接受者receiver的所有关联

disconnect(sender, 0, receiver, 0); 
相当于:
sender->disconnect(SIGNAL(single1()));

 
4. 断开指定信号与槽的关联:

//断开了 single1() 信号, 与 slotFun() 槽函数的连接
disconnect(sender, SIGNAL(single1()), receiver, SLOT(slotFun())); 

或者:
//使用connect的返回值
QMetaObject::Connection ret = connect(sender, SIGNAL(single1()), receiver, SLOT(slotFun())); 
disconnect(ret);	//ret为connect()的返回值
如:

 
 
 

信号与槽机制的优越性:

  1. 信号与槽机制是类型安全的,相关联的信号与槽参数必须匹配
  2. 信号与槽是松耦合的,信号发送者不知道也不需知道接受者的信息。
  3. 信号与槽可以使用任意类型的任意数量的参数。

你可能感兴趣的:(Qt,信号与槽)