Qt自定義訊號槽

2021-07-04 07:28:14 字數 2858 閱讀 8406

qt自定義訊號槽,在控制台程式中實現(qt5)

**如下:

//!!! qt5

#include

//////

//// news*****.h

class news***** : public qobject

void send()

signals:

void new*****(const qstring &name);

private:

qstring m_name;

};///

/////// reader.h

#include

#include

class reader : public qobject

void receivenews*****(const qstring & name)

};///

/////// main.cpp

#include "news*****.h"

#include "reader.h"

int main(int argc, char *argv)

(上述 標頭檔案是在編譯過程中自己新增)

當我們執行上面的程式時,會看到終端輸出 receives news*****: news***** a 這樣的字樣。

這段**放在了三個檔案,分別是 news*****.h,reader.h 和 main.cpp。為了減少檔案數量,

可以把 news*****.h 和 reader.h 都放在 main.cpp 的 main() 函式之前嗎?答案是,可以,

但是需要有額外的操作。具體問題,我們在下面會詳細說明。

首先看 news***** 這個類。這個類繼承了 qobject 類。只有繼承了 qobject 類的類,才具

有訊號槽的能力。所以,為了使用訊號槽,必須繼承 qobject。凡是 qobject 類(不管是直接

子類還是間接子類),都應該在第一行**寫上 q_object。不管是不是使用訊號槽,都應該

新增這個巨集。這個巨集的展開將為我們的類提供訊號槽機制、國際化機制以及 qt 提供的不基於

c++ rtti 的反射能力。因此,如果你覺得你的類不需要使用訊號槽,就不新增這個巨集,就是錯

誤的。其它很多操作都會依賴於這個巨集。注意,這個巨集將由 moc(我們會在後面章節中介紹 moc。

這裡你可以將其理解為一種預處理器,是比 c++ 預處理器更早執行的預處理器。) 做特殊處

理,不僅僅是巨集展開這麼簡單。moc 會讀取標記了 q_object 的標頭檔案,生成以 moc_ 為前

綴的檔案,比如 news*****.h 將生成 moc_news*****.h。你可以到構建目錄檢視這個檔案,

看看到底增加了什麼內容。注意,由於 moc 只處理標頭檔案中的標記了 q_object 的類宣告,

不會處理 cpp 檔案中的類似宣告。因此,如果我們的 news***** 和 reader 類位於 main.cpp

中,是無法得到 moc 的處理的。解決方法是,我們手動呼叫 moc 工具處理 main.cpp,並且

將 main.cpp 中的 include 「news*****.h」 改為 include 「moc_news*****.h」 就可以了。不過,

這是相當繁瑣的步驟,為了避免這樣修改,我們還是將其放在標頭檔案中。許多初學者會遇到莫名

其妙的錯誤,一加上 q_object 就出錯,很大一部分是因為沒有注意到這個巨集應該放在標頭檔案

中。news***** 類的 public 和 private **塊都比較簡單,只不過它新加了乙個 signals。signals

塊所列出的,就是該類的訊號。訊號就是乙個個的函式名,返回值是 void(因為無法獲得訊號

的返回值,所以也就無需返回任何值),引數是該類需要讓外界知道的資料。訊號作為函式名,

不需要在 cpp 函式中新增任何實現(我們曾經說過,qt 程式能夠使用普通的 make 進行編譯。

沒有實現的函式名怎麼會通過編譯?原因還是在 moc,moc 會幫我們實現訊號函式所需要的函

數體,所以說,moc 並不是單純的將 q_object 展開,而是做了很多額外的操作)。

news***** 類的 send() 函式比較簡單,只有乙個語句 emit new*****(m_name);。emit 是 qt

對 c++ 的擴充套件,是乙個關鍵字(其實也是乙個巨集)。emit 的含義是發出,也就是發出 new*****()

訊號。感興趣的接收者會關注這個訊號,可能還需要知道是哪份報紙發出的訊號?所以,我們將

實際的報紙名字 m_name 當做引數傳給這個訊號。當接收者連線這個訊號時,就可以通過槽函

數獲得實際值。這樣就完成了資料從發出者到接收者的乙個轉移。

reader 類更簡單。因為這個類需要接受訊號,所以我們將其繼承了 qobject,並且新增了

q_object 巨集。後面則是預設建構函式和乙個普通的成員函式。qt 5 中,任何成員函式、static

函式、全域性函式和 lambda 表示式都可以作為槽函式。與訊號函式不同,槽函式必須自己完成

實現**。槽函式就是普通的成員函式,因此也會受到 public、private 等訪問控制符的影響。

(我們沒有說訊號也會受此影響,事實上,如果訊號是 private 的,這個訊號就不能在類的外面

連線,也就沒有任何意義。)

main() 函式中,我們首先建立了 news***** 和 reader 兩個物件,然後使用

qobject::connect() 函式。這個函式我們上一節已經詳細介紹過,這裡應該能夠看出這個連線的

含義。然後我們呼叫 news***** 的 send() 函式。這個函式只有乙個語句:發出訊號。由於我

們的連線,當這個訊號發出時,自動呼叫 reader 的槽函式,列印出語句。

Qt 自定義訊號槽

使用 connect 可以讓我們連線系統提供的訊號和槽。但是,qt 的訊號槽機制並不僅僅是使用系統提供的那部分,還會允許我們自己設計自己的訊號和槽。這也是 qt 框架的設計思路之一,用於我們設計解耦的程式。本節將講解如何在自己的程式中自定義訊號槽。訊號槽不是 gui 模組提供的,而是 qt 核心特性...

QT 3 自定義訊號槽

include subwdget.h subwdget subwdget qwidget parent qwidget parent void subwdget senslot ifndef subwdget h define subwdget h include include class sub...

Qt開發學習(3)自定義訊號槽

使用 connect 可以讓我們連線系統提供的訊號和槽。但是,qt 的訊號槽機制並不僅僅是使用系統提供的那部分,還會允許我們自己設計自己的訊號和槽。訊號槽不是 gui 模組提供的,而是 qt 核心特性之一。因此,可以在普通的控制台程式使用訊號槽。經典的觀察者模式在講解舉例的時候通常會舉報紙和訂閱者的...