Qt信號與槽機制(signal & slot)

1、簡介

信號槽機制與Windows下消息機制類似,消息機制是基於回調函數,Qt中用信號與槽來代替函數指針,使程序更安全簡潔。

信號和槽機制是 Qt 的核心機制,可以讓編程人員將互不相關的對象綁定在一起,實現對象之間的通信。

信號

當對象改變其狀態時,信號就由該對象發射 (emit) 出去,而且對象只負責發送信號,它不知道另一端是誰在接收這個信號。這樣就做到了真正的信息封裝,能確保對象被當作一個真正的軟件組件來使用。

用於接收信號,而且槽只是普通的對象成員函數。一個槽並不知道是否有任何信號與自己相連接。而且對象並不瞭解具體的通信機制。

信號與槽的連接

所有從 QObject 或其子類 ( 例如 Qwidget ) 派生的類都能夠包含信號和槽。因爲信號與槽的連接是通過 QObject 的 connect() 成員函數來實現的。

connect(sender, SIGNAL(signal), receiver, SLOT(slot));
其中 sender 與 receiver 是指向對象的指針,SIGNAL() 與 SLOT() 是轉換信號與槽的宏。

2、特點

一個信號可以連接多個槽

當信號發射時,會以不確定的順序一個接一個的調用各個槽。

多個信號可以連接同一個槽

即無論是哪一個信號被髮射,都會調用這個槽。

信號直接可以相互連接

發射第一個信號時,也會發射第二個信號。

連接可以被移除

這種情況用得比較少,因爲在對象被刪除時,Qt會自動移除與這個對象相關的所有連接。語法如下:

disconnect(sender, SIGNAL(signal), receiver, SLOT(slot));

3、注意事項

信號與槽機制與普通函數的調用一樣,如果使用不當的話,在程序執行時也有可能產生死循環。

因此,在定義槽函數時一定要注意避免間接形成無限循環,即在槽中再次發射所接收到的同樣信號。例如 , 在前面給出的例子中如果在 mySlot() 槽函數中加上語句 emit mySignal() 即可形成死循環。

Qt4.6以後連接到同一個信號的多個槽的執行順序是確定的,按connect的先後順序。

宏定義不能用在 signal 和 slot 的參數中。

信號和槽的參數個數與類型必須一致。

4、程序舉例

這個demo程序由一個Label和PushButton組成,點擊按鈕,在label上獲取當前系統時間,這個涉及到的知識點有:信號與槽的參數類型不同時如何連接、自定義槽函數、自定義信號。

4.1 新建一個Qt Application,Base Class選擇QDialog,類名爲getTime

4.2 getTime.h內容

#ifndef GETTIME_H
#define GETTIME_H

#include <QtWidgets/QDialog>
#include <QtWidgets/QLabel>
#include <QtWidgets/QPushButton>
#include <QTime>
#include "ui_gettime.h"

class getTime : public QDialog
{
	Q_OBJECT

public:
	getTime(QWidget *parent = 0);
	~getTime();

private:
	Ui::getTimeClass ui;
	QLabel *label;
	QPushButton *btn;

	public slots:
		void currentTime();

signals:
		void getData(QString);	
};


#endif // GETTIME_H

4.3 getTime.cpp內容

#include "gettime.h"

getTime::getTime(QWidget *parent)
	: QDialog(parent)
{
	this->resize(300,400);
	label = new QLabel("label",this);
	btn = new QPushButton("getTime",this);
	label->move(150,200);
	btn->move(125,300);

	connect(btn,SIGNAL(clicked()),this,SLOT(currentTime()));

	connect(this,SIGNAL(getData(QString)),label,SLOT(setText(QString)));

	ui.setupUi(this);
}

getTime::~getTime()
{
	delete label;
	delete btn;
}

void getTime::currentTime()
{
	emit getData(QTime::currentTime().toString("hh:mm"));
}





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章