一、信号與槽的了解
1、什麼是信号和槽?
在許多GUI工具中,每一個視窗部件都有一個回調函數用于響應他們能夠觸發的動作,這些回調函數通常是一個指向某個函數的指針。指針是一個相對麻煩的概念,在Qt中信号與槽取代了這些淩亂的函數指針,使得程式的編寫更為簡單。
當一個對象發生改變的時候,信号就由這個對象發射出去,這就是這個對象要做的全部事情,它并不知道另一端是誰在接收信号,這個過程就是真正的資訊封裝,實作了絕對的安全。
槽用于接收信号,它們是普通的c++成員函數,它們并不知道是否有信号與自己關聯,而且對象并不了解通信機制
在Qt中,當點選一個按鈕的時候,這個按鈕會發出一個信号,而這個信号會傳遞給另外一個對象,接收到信号的對象會産生相應的動作,這就是信号與槽的機制
2、信号與槽的關聯
1)、信号與槽通過
QObject::connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::Connection type=Qt::AutoCompatConnection)産生關聯
sender,信号的發送者
signal,待發送的信号
receiver,信号的接收者
method,槽函數
type,信号與槽的關聯方式
2)、type有3種類型
Qt::DirectConnection,信号發送後立即傳遞給槽,隻有槽函數執行完畢傳回之後,發送信号"emit"之後的代碼才能被執行
Qt::QueueConnection,信号發送後排隊,直到事件循環有能力将它傳遞給槽,而不管槽函數有沒有執行,發送信号"emit"之後的代碼
立即被執行
Qt::AutoCompatConnection,如果信号和槽在同一個線程,等同于Qt::DirectConnection;如果信号和槽不在同一個線程,那麼等同于
Qt::QueueConnection。
二、信号與槽的執行個體
1、信号
當對象的内部狀态發生改變,信号就被發射,隻有定義了一個信号的類和它的子類才能發射這個信号。例如QPushButton類中就預定義了clicked信号,當按鈕被點選時,就會發射clicked信号。
在Qt中除了系統預定義的信号外,也可以自定義信号
信号的聲明在頭檔案中,以關鍵字signals開頭
signals:
void signals();
void signals(int x);
這裡面有兩個信号,最然名字一樣,但是攜帶的參數不一樣,有點類似于函數的重載。
信号類似一個普通的C++函數,但是它沒有實體,隻有一個空殼,而且它的傳回值永遠是void,不要期待從信号中傳回有用的資訊。信号聲明好以後,有moc工具自動産生,是以不應該放在.cpp檔案中。
系統預定義信号一般會自動發射,不需要我們關心,如果需要手動發射信号,可以這樣寫emit signals();
2、槽
槽是普通的C++成員函數,可以被正常的調用,很多信号可以與槽進行關聯。既然槽是一個普通的成員函數,那麼它也有權限。是以有3種類型的槽函數,public slots,private slots, protect slots
槽函數的申明也是在頭檔案中
private slots:
void mySlot1();
void mySlot1(int x);
在信号和槽函數的聲明之前,必須加一個宏Q_OBJECT,隻有這樣Qt才會認識它們
3、元對象工具
moc工具會對c++檔案中的類的聲明進行初始化,自動産生用于初始化元對象的c++代碼,元對象包含全部的信号和槽,以及指向這些名字的指
針。
moc讀取c++源檔案,如果發現有Q_OBJECT宏聲明的類,它就會生成另外的c++源檔案。moc工具不擴充#define,是以信号和槽函數中不能有宏定義
4、關聯
信号與槽的關聯通過函數connect
btn = new QPushButton();
lab = new QLabel();
connect(btn, SIGNAL(clicked()), lab, SLOT(clear()))
信号需要使用宏SIGNAL(),槽函數需要使用宏SLOT();
信号和槽的參數一定要一緻;
當信号和槽屬于同一對象時,信号的接收者可以省略
connect(btn, SIGNAL(clicked()), SLOT(showMenu()))
信号和槽應該注意的問題
1)、構造函數不能在信号和槽的區域内
2)、函數指針不能做為信号和槽的參數
3)、信号和槽不能有預設的參數
4)、信号和槽不能帶有模闆類參數
5)、嵌套的類不能位于信号和槽區域,也不能有信号和槽