在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

一文詳解Qt信號和槽函數(shù)機(jī)制

嵌入式小生 ? 來源:嵌入式小生 ? 2023-02-07 09:14 ? 次閱讀

一、信號和槽函數(shù)機(jī)制簡介

(注1:下文中的槽函數(shù)表示一個意思)

(注2:閱讀本文可能有點(diǎn)枯燥,但文中有關(guān)于信號和槽的重要知識,這些知識甚至在開發(fā)中經(jīng)常被忽略。請君繼續(xù)下看)

信號和槽用于多個對象之間的通信。信號和槽機(jī)制是Qt的核心特性,也是Qt與其他框架最大的不同之處。Qt的元對象系統(tǒng)是信號和槽實(shí)現(xiàn)的基礎(chǔ)。

在GUI編程中,當(dāng)更改一個小部件時,通常希望另一個小部件得到通知。希望任何類型的對象之間都能夠相互通信。例如,如果用戶單擊關(guān)閉按鈕,可能希望調(diào)用窗口的Close()函數(shù)。

其他軟件工具包或框架可能使用回調(diào)機(jī)制實(shí)現(xiàn)這種通信機(jī)制。一個回調(diào)函數(shù)是一個指向一個函數(shù)的指針,所以如果想讓一個處理函數(shù)通知一些事件,可以向處理函數(shù)傳遞一個指向另一個函數(shù)(回調(diào)函數(shù))的指針,然后處理函數(shù)在適當(dāng)?shù)臅r候調(diào)用回調(diào)函數(shù)。雖然使用這種方法的成功框架確實(shí)存在,但回調(diào)可能不太直觀,在確保回調(diào)參數(shù)類型的正確性上可能會存在問題。

在Qt中,有一種回調(diào)技術(shù)的替代方法:那就是信號和槽機(jī)制。當(dāng)特定事件發(fā)生時,會發(fā)出一個信號。Qt的小部件中有許多預(yù)定義的信號,但我們可以將小部件子類化,向它們添加自定義的信號。槽是響應(yīng)特定信號的函數(shù)。Qt的小部件有許多預(yù)定義的槽函數(shù),但是通常是子類化小部件并添加自己的槽函數(shù),這樣就可以處理與之相關(guān)聯(lián)的信號了。如下圖所示:

04cb0034-a62a-11ed-bfe3-dac502259ad0.png

信號和槽機(jī)制是類型安全的:信號的參數(shù)必須與槽函數(shù)的參數(shù)相匹配。(實(shí)際上,槽的參數(shù)可以比它接收到的信號參數(shù)更少,因?yàn)椴劭梢院雎灶~外的參數(shù))由于參數(shù)是兼容的,所以在使用基于函數(shù)指針語法的信號與槽關(guān)聯(lián)機(jī)制時,編譯器可以幫助檢測類型是否匹配,從而可以檢測出在開發(fā)中信號和槽函數(shù)關(guān)聯(lián)時出現(xiàn)的問題。

信號和槽函數(shù)是松耦合的:當(dāng)一個對象發(fā)出信號,該對象不知道也不關(guān)心哪個對象的槽函數(shù)會接收這個信號。Qt的信號和槽函數(shù)機(jī)制確保:如果將一個信號連接到一個槽函數(shù)上,該槽函數(shù)將在正確的時間被調(diào)用。信號和槽函數(shù)可以接受任意數(shù)量的任意類型的參數(shù)。它們完全是類型安全的。所有從QObject或它的一個子類(例如,QWidget)繼承的類都可以使用信號和槽槽函數(shù)機(jī)制。當(dāng)對象改變其狀態(tài)時,可能就會發(fā)出信號(這一點(diǎn)由開發(fā)人員和父類確定其關(guān)聯(lián)的信號什么時候發(fā)出)。

槽函數(shù)用來接收信號,但也是普通的成員函數(shù)。就像對象不知道是否有東西接收到它的信號一樣,槽函數(shù)也不知道是否有信號連接到它,因此可以創(chuàng)建獨(dú)立的軟件組件。當(dāng)需要使用該獨(dú)立組件時,確定其組件類中預(yù)定義的信號和槽函數(shù),然后關(guān)聯(lián)信號和槽函數(shù)即可。

可以將多個信號連接到一個槽函數(shù)上(即【多對一】),而一個信號也可以連接到多個槽函數(shù)上【即一對多】。

也可以將一個信號直接連接到另一個信號。(當(dāng)?shù)谝粋€信號發(fā)出時,它將立即發(fā)出第二個信號。)

綜上,在Qt中,信號和槽函數(shù)共同構(gòu)成了一個功能強(qiáng)大的組件編程機(jī)制。

二、信號

(2-1)信號的發(fā)出

由于某種條件到達(dá)可能引起了對象改變,其內(nèi)部狀態(tài)將發(fā)生改變,這時候?qū)ο缶蜁l(fā)出信號。信號是公共訪問函數(shù),可以從任何地方發(fā)出,但是建議:【只從定義該信號的類及其子類發(fā)出信號】。

在Qt框架下,信號發(fā)出分為兩種:

1、【每個類預(yù)定義的信號】:這些信號何時發(fā)出可以通過查看官方文檔獲知。

2、【自定義的信號】:這些信號的發(fā)出由開發(fā)人員自行定義。

(2-2)信號的處理

當(dāng)一個信號發(fā)出時,連接到它的槽函數(shù)通常會立即執(zhí)行,就像一個普通函數(shù)調(diào)用一樣。在這種情況下,信號和槽函數(shù)機(jī)制是完全獨(dú)立于GUI事件循環(huán)的,也并不會干擾GUI的事件循環(huán)。emit語句之后的代碼將在所有槽函數(shù)都返回之后才執(zhí)行。如果使用排隊(duì)連接(queued connections),情況略有不同,在這種情況下,emit關(guān)鍵字后面的代碼將立即繼續(xù),槽函數(shù)將在后續(xù)執(zhí)行。

如果幾個槽函數(shù)連接到同一個信號上,當(dāng)信號發(fā)出時,這些槽函數(shù)將按照它們連接時的順序依次執(zhí)行【這一點(diǎn)很重要】。

信號是由moc工具自動生成,不能在.cpp文件中實(shí)現(xiàn),所以信號永遠(yuǎn)不能有返回類型(必須使用void關(guān)鍵字定義信號)。

關(guān)于信號和槽參數(shù)的注意事項(xiàng):經(jīng)驗(yàn)表明,如果信號和槽函數(shù)不使用特殊類型,那么代碼具有極強(qiáng)的可重用性。

下表是使用connect()創(chuàng)建信號和槽函數(shù)連接時,可以指定5種不同的連接類型:

序號 類型 含義
1 Qt::AutoConnection 如果接收者生活在發(fā)出信號的線程中,Qt::DirectConnection被使用。否則,使用Qt::QueuedConnection。連接類型是在信號發(fā)出時確定。【這是Qt創(chuàng)建信號和槽函數(shù)時的默認(rèn)連接方式】
2 Qt::DirectConnection 當(dāng)信號發(fā)出時,槽函數(shù)立即被調(diào)用。槽函數(shù)在發(fā)送信號的線程中執(zhí)行。
3 Qt::QueuedConnection 當(dāng)控制返回到接收方線程的事件循環(huán)時,將調(diào)用槽函數(shù)。槽函數(shù)在接收方的線程中執(zhí)行。
4 Qt::BlockingQueuedConnection 與Qt::QueuedConnection相同,只是在槽函數(shù)返回之前線程會阻塞。如果接收方存在于發(fā)送信號的線程中,則不能使用此連接,否則應(yīng)用程序?qū)梨i。
5 Qt::UniqueConnection 這是一個標(biāo)志,可以使用按位OR與上述的連接類型進(jìn)行組合。當(dāng)Qt::UniqueConnection被設(shè)置時,如果連接已經(jīng)存在,QObject::connect()將失敗(例如,如果相同的信號已經(jīng)連接到同一對對象的相同槽位)。注:這個標(biāo)志在Qt 4.6中引入。

三、槽函數(shù)

當(dāng)一個連接到槽函數(shù)的信號被發(fā)射時,槽函數(shù)將被調(diào)用。槽函數(shù)是普通的C++函數(shù),在實(shí)際開發(fā)中也可以正常調(diào)用;它們唯一的特點(diǎn)是:【信號可以與它們相連接】。

由于槽是普通的成員函數(shù),所以它們在直接調(diào)用時遵循普通的C++規(guī)則。但是,作為槽函數(shù)時,任何組件都可以通過信號連接從而調(diào)用它們。

還可以將槽函數(shù)定義為虛擬的,這在開發(fā)中非常有用。

與回調(diào)機(jī)制相比,信號和槽函數(shù)機(jī)制的速度稍微慢一些,這一點(diǎn)對于實(shí)際應(yīng)用程序來說,這種差別并不顯著。一般來說,發(fā)送一個連接到某些槽函數(shù)的信號,比直接調(diào)用非虛函數(shù)要慢大約10倍。這是定位連接對象、安全地遍歷所有連接(即檢查后續(xù)接收方在發(fā)射過程中沒有被銷毀)以及以函數(shù)調(diào)用增加的開銷。雖然10個非虛函數(shù)調(diào)用聽起來很多,但是它比new操作或delete操作的開銷要小得多。一旦在后臺執(zhí)行一個需要new或delete的字符串、向量或列表操作,信號和槽函數(shù)的開銷只占整個函數(shù)調(diào)用開銷的很小一部分。在槽函數(shù)中執(zhí)行系統(tǒng)調(diào)用時也是如此(或間接調(diào)用超過十個函數(shù))。因此信號和槽函數(shù)機(jī)制的簡單性和靈活性是值得的,這些開銷在實(shí)際應(yīng)用場景下甚至不會注意到。

注意,當(dāng)與基于Qt的應(yīng)用程序一起編譯時,定義為信號或槽的變量的第三方庫可能會導(dǎo)致編譯器出現(xiàn)警告和錯誤。要解決這個問題,使用#undef來定義出錯的預(yù)處理器符號即可。

(3-1)帶有默認(rèn)參數(shù)的信號和槽函數(shù)

信號和槽可以包含參數(shù),參數(shù)可以有默認(rèn)值。例如:QObject::destroyed():

voiddestroyed(QObject*=nullptr);

當(dāng)QObject被刪除時,它會發(fā)出這個QObject::destroyed()信號。無論我們在哪里有一個懸空引用指向已刪除的QObject,都希望捕捉到這個信號,這樣就可以清除它。合適的槽參數(shù)可以是:

voidobjectDestroyed(QObject*obj=nullptr);

(3-2)使用QObject::connect()將信號連接到槽函數(shù)的三種方法

1、第一種方法:使用函數(shù)指針

connect(sender,&QObject::destroyed,this,&MyObject::objectDestroyed);

將QObject::connect()與函數(shù)指針一起使用有幾個優(yōu)點(diǎn)。它允許編譯器檢查信號的參數(shù)是否與槽的參數(shù)兼容。當(dāng)然,編譯器還可以隱式地轉(zhuǎn)換參數(shù)。

2、第二種方法:連接到C++ 11的lambdas

connect(sender,&QObject::destroyed,this,[=](){this->m_objects.remove(sender);});

在這種情況下,我們在connect()調(diào)用中提供這個上下文。上下文對象提供關(guān)于應(yīng)該在哪個線程中執(zhí)行接收器的信息。

當(dāng)發(fā)送方或上下文被銷毀時,lambda將斷開連接。注意:當(dāng)信號發(fā)出時,函數(shù)內(nèi)部使用的所有對象依然是激活的。

3、第三種方法:使用QObject::connect()以及信號和槽聲明宏。

在SIGNAL()和SLOT()宏中包含參數(shù)(如果參數(shù)有默認(rèn)值)的規(guī)則是:傳遞給SIGNAL()宏的參數(shù)不能少于傳遞給SLOT()宏的參數(shù)

例如以下代碼都是合法的:

connect(sender,SIGNAL(destroyed(QObject*)),this,SLOT(objectDestroyed(Qbject*)));
connect(sender,SIGNAL(destroyed(QObject*)),this,SLOT(objectDestroyed()));
connect(sender,SIGNAL(destroyed()),this,SLOT(objectDestroyed()));

但是這種是非法的:

connect(sender,SIGNAL(destroyed()),this,SLOT(objectDestroyed(QObject*)));

因?yàn)椴酆瘮?shù)期望的是一個信號不會發(fā)送的QObject。此連接將報(bào)告運(yùn)行時錯誤。

注意,使用這種方法時,在使用QObject::connect()關(guān)聯(lián)信號和槽函數(shù)時,編譯器不會自動檢查信號和槽函數(shù)的參數(shù)之間是否匹配。

綜上:使用第一種方法 創(chuàng)建信號和槽 在開發(fā)中較為常用,也較為合適。

(3-3)信號和槽函數(shù)的一些高級用法

當(dāng)需要獲取信號發(fā)送方的信息時,使用Qt提供QObject::sender()函數(shù),該函數(shù)返回一個指向發(fā)送信號對象的指針。

Lambda表達(dá)式是傳遞自定義參數(shù)到槽的一種方便方式:

connect(action,&QAction::triggered,engine,[=](){engine->processAction(action->text());});

四、使用disconnect斷開信號/槽連接

disconnect()用于斷開對象發(fā)送器中的信號與對象接收器中的方法的連接。如果連接成功斷開,則返回true;否則返回false。

當(dāng)對信號/槽關(guān)聯(lián)的兩方中的任何一個對象進(jìn)行銷毀時,信號/槽連接將被移除。

disconnect()有三種使用方法,如下示例所示:

1、斷開所有與對象相連的信號/槽:

disconnect(myObject,nullptr,nullptr,nullptr);

相當(dāng)于非靜態(tài)重載函數(shù):

myObject->disconnect();

2、斷開所有與特定信號相連的對象:

disconnect(myObject,SIGNAL(mySignal()),nullptr,nullptr);

相當(dāng)于非靜態(tài)重載函數(shù):

myObject->disconnect(SIGNAL(mySignal()));

3、斷開特定接收對象的連接:

disconnect(myObject,nullptr,myReceiver,nullptr);

相當(dāng)于非靜態(tài)重載函數(shù):

myObject->disconnect(myReceiver);

nullptr可以用作通配符,分別表示“任何信號”、“任何接收對象”或“接收對象中的任何槽”。

如下格式的使用示例:

disconnect(發(fā)送對象,信號,接收對象,方法)

發(fā)送對象不會是nullptr。

如果信號為nullptr,將斷開接收對象槽函數(shù)與所有信號的連接。否則只斷開指定的信號。

如果接收對象是nullptr,它斷開所有關(guān)聯(lián)該信號的連接。否則,只斷開與接收對象的槽函數(shù)連接。

如果方法是nullptr,它會斷開任何連接到接收對象的連接。如果不是,只有命名為方法的槽函數(shù)連接將被斷開。如果沒有接收對象方法必須為nullptr。即:

disconnect(發(fā)送對象,信號,nullptr,nullptr)

五、使用Qt與第三方信號和槽函數(shù)

當(dāng)?shù)谌綆熘幸灿行盘?槽函數(shù)機(jī)制時,這時候又需要使用Qt的信號和槽函數(shù)機(jī)制。對于這種開發(fā)場景,Qt可以在同一個項(xiàng)目中使用這兩種機(jī)制。需將下面一行添加到qmake項(xiàng)目(.pro)工程配置文件中:

CONFIG+=no_keywords

該配置將告訴Qt不要定義moc關(guān)鍵字信號、槽函數(shù)和emit,因?yàn)檫@些名稱將被第三方庫使用(例如Boost)。如果要在使用no_keywords標(biāo)志下繼續(xù)使用Qt信號和槽機(jī)制,需將源文件中所有的Qt moc關(guān)鍵字替換為對應(yīng)的Qt宏:Q_SIGNALS(或Q_SIGNAL)、Q_SLOT(或Q_SLOT)和Q_EMIT。

六、總結(jié)

本文站在開發(fā)的角度,描述了Qt的信號和槽函數(shù)機(jī)制。

審核編輯:湯梓紅
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • 信號
    +關(guān)注

    關(guān)注

    11

    文章

    2844

    瀏覽量

    77950
  • 函數(shù)
    +關(guān)注

    關(guān)注

    3

    文章

    4372

    瀏覽量

    64292
  • Qt
    Qt
    +關(guān)注

    關(guān)注

    1

    文章

    313

    瀏覽量

    38844
  • GUI
    GUI
    +關(guān)注

    關(guān)注

    3

    文章

    677

    瀏覽量

    40811
  • 回調(diào)函數(shù)
    +關(guān)注

    關(guān)注

    0

    文章

    88

    瀏覽量

    11833

原文標(biāo)題:Qt信號和槽函數(shù)機(jī)制,此篇足矣

文章出處:【微信號:嵌入式小生,微信公眾號:嵌入式小生】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦
    熱點(diǎn)推薦

    Qt信號機(jī)制()

    . 簡介就我個人來理解,信號機(jī)制與Windows下消息機(jī)制類似,消息機(jī)制是基于回調(diào)
    發(fā)表于 11-07 15:06

    Qt信號例子(二)

    (){label->setText("clicked");//發(fā)送自定義的信號,請注意信號的參數(shù)類型和個數(shù)要和樣emit SigTest("Hello,I am
    發(fā)表于 11-07 15:13

    QT自動鏈接信號機(jī)制

    name中的信號signal name和這個void on__()鏈接起來。這是QT不需要connect語句就可以自動鏈接信號
    發(fā)表于 11-13 09:17

    給初學(xué)Qt者的小TIP

    自己的信號。 ‘’就是個可以被調(diào)用處理特定信號函數(shù)。Qt 的窗口部件也有很多預(yù)定義的
    發(fā)表于 10-18 10:10

    給初學(xué)Qt者的小TIP

    是無參數(shù)名的函數(shù)信號?!?b class='flag-5'>信號和機(jī)制用于 Qt 對象間的通訊。 “
    發(fā)表于 11-05 11:33

    請問Qt編程中信號信號處理程序的使用方法?

      信號作為Qt的和新機(jī)制,在Qt編程中有著非常廣泛的應(yīng)用。  事實(shí)上,我們在Qt開發(fā)中,要
    發(fā)表于 11-20 08:03

    怎樣通過Qt界面控制步進(jìn)電機(jī)的啟停

    Widget用于顯示。2,在你的類中添加按鈕控trolMachine函數(shù)之間的信號機(jī)制(使用connect函數(shù))。3,完善你的contr
    發(fā)表于 06-29 07:16

    信號是如何實(shí)現(xiàn)連接的呢

    1.的連接過程分析Unix Signal產(chǎn)生者(鍵盤) --> 綁定[signal(id,某函數(shù)())] --> 接受者(“.c文件中的函數(shù)處理”)Qt
    發(fā)表于 01-18 09:48

    簡單概述下窗口之間傳遞參數(shù)的機(jī)制

    (connect):走路去結(jié)果(void):張三得到煙窗口(B):商店函數(shù)(slots):商店給張三煙能看完的才能學(xué)到點(diǎn)東西。如上所述:QT采用信號
    發(fā)表于 01-18 09:01

    基于Qt組件的俄羅斯方塊設(shè)計(jì)

    函數(shù)的指針的回調(diào)函數(shù)響應(yīng)觸發(fā)的每個動作。而在QT信號取代了函數(shù)指針,且能攜帶任意數(shù)量和類
    發(fā)表于 11-15 15:16 ?9次下載

    Qt5位置相關(guān)函數(shù)及圖形與圖片的詳細(xì)資料免費(fèi)下載

    本文檔的主要內(nèi)容詳細(xì)介紹的是Qt5位置相關(guān)函數(shù)及圖形與圖片的詳細(xì)資料免費(fèi)下載內(nèi)容包括了:Qt 5位置相關(guān)函數(shù),Qt 5基礎(chǔ)圖形的繪制,
    發(fā)表于 08-01 08:00 ?0次下載
    <b class='flag-5'>Qt</b>5位置相關(guān)<b class='flag-5'>函數(shù)</b>及圖形與圖片的詳細(xì)資料免費(fèi)下載

    Qt編程基礎(chǔ)之信號機(jī)制

    在使用信號的類中,必須在類的定義中加入宏Q_OBJECT。當(dāng)信號被發(fā)射時,與其關(guān)聯(lián)的函數(shù)
    的頭像 發(fā)表于 09-06 13:01 ?1275次閱讀

    Qt“懶人寫法”之鍵破“

    在《Qt信號函數(shù)機(jī)制,此篇足矣》中已經(jīng)描述了
    的頭像 發(fā)表于 02-09 17:23 ?1342次閱讀

    Qt“靈魂”之Meta-Object系統(tǒng)

    Meta-Object即是Qt的元對象系統(tǒng),下文都以元對象系統(tǒng)進(jìn)行描述。在Qt中,具有標(biāo)志性特征的則是信號函數(shù)
    的頭像 發(fā)表于 02-10 13:50 ?2611次閱讀

    詳細(xì)介紹Qt信號交流機(jī)制

    PyQT5中QGUI中當(dāng)用戶改動個QWidget的狀態(tài)時,可以通過支持的信號觸發(fā)相關(guān)的函數(shù)完成動作交互。
    的頭像 發(fā)表于 02-21 09:35 ?1405次閱讀
    主站蜘蛛池模板: 亚洲一区二区三区中文字幕5566 | 免费高清特黄a 大片 | 欧美日本视频一区 | 亚洲加勒比在线 | 欧美一级片手机在线观看 | 人人干网站 | 麻豆美女大尺度啪啪 | 九色 在线| 26uuu欧美日本 | 一级毛片一片毛 | 老子影院午夜精品欧美视频 | 午夜禁片| 高h文男主又粗又狠 | 国产福利观看 | 色综合久久98天天综合 | 免费黄视频网站 | 日本a级片在线播放 | 在线观看黄的网站 | 天天免费视频 | 日本最新免费网站 | 亚洲午夜大片 | 亚洲成人资源 | 亚洲偷图色综合色就色 | 国产一级特黄aaaa大片野外 | hs网站免费 | 亚洲三级视频在线观看 | 5g影院午夜伴侣 | 久久精品国产99精品最新 | 丁香综合激情 | 2021国产精品午夜久久 | 在线视频播放大全 | 日韩一区二区三区在线 | 特黄特色大片免费播放路01 | 国产综合视频在线 | 欧美日本一道免费一区三区 | 色综合久久98天天综合 | 色婷婷综合久久久中文字幕 | 美女扒开尿口给男人桶动态图 | 黄网站播放| 免费抓胸吻胸激烈视频网站 | 99热久久精品免费精品 |