淺談Qt信號(hào)與槽的各種連接方式
簡(jiǎn)介
信號(hào)槽是 Qt 框架引以為豪的機(jī)制之一。當(dāng)用戶(hù)觸發(fā)某個(gè)事件時(shí),就會(huì)發(fā)出一個(gè)信號(hào)(signal),這種發(fā)出是沒(méi)有目的的,類(lèi)似廣播。如果有對(duì)象對(duì)這個(gè)信號(hào)感興趣,它就會(huì)連接(connect)綁定一個(gè)函數(shù)(稱(chēng)為槽slot)來(lái)處理這個(gè)信號(hào)。也就是說(shuō)當(dāng)信號(hào)發(fā)出時(shí),被連接的槽函數(shù)會(huì)自動(dòng)被回調(diào)。這有點(diǎn)類(lèi)似與開(kāi)發(fā)模式中的觀(guān)察者模式,即當(dāng)發(fā)生了感興趣的事件,某一個(gè)操作就會(huì)被自動(dòng)觸發(fā)
信號(hào)和槽是Qt特有的信息傳輸機(jī)制,是Qt設(shè)計(jì)程序的重要基礎(chǔ),它可以讓互不干擾的對(duì)象建立一種聯(lián)系。槽的本質(zhì)是類(lèi)的成員函數(shù),其參數(shù)可以是任意類(lèi)型的。和普通C++成員函數(shù)幾乎沒(méi)有區(qū)別,它可以是虛函數(shù),也可以被重載??梢允枪械?、保護(hù)的、私有的、也可以被其他C++成員函數(shù)調(diào)用。唯一區(qū)別的是:槽可以與信號(hào)連接在一起,每當(dāng)和槽連接的信號(hào)被發(fā)射的時(shí)候,就會(huì)調(diào)用這個(gè)槽
連接信號(hào)槽 connect 函數(shù)的第五個(gè)參數(shù)
connect 函數(shù)原型如下:
[static] QMetaObject::Connection QObject::connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type = Qt::AutoConnection)
ConnectionType 是一個(gè)定義在 Qt namespace 中的一個(gè)枚舉,具體內(nèi)容如下:
enum ConnectionType { AutoConnection, DirectConnection, QueuedConnection, BlockingQueuedConnection, UniqueConnection = 0x80 };
- Qt::AutoConnection:默認(rèn)值。根據(jù) sender 和 receiver 所處線(xiàn)程在信號(hào)發(fā)出時(shí)作出判斷。如果在同一線(xiàn)程則使用 Qt::DirectConnection 連接,否則使用 Qt :: QueuedConnection 連接。需要注意的是,這個(gè)判斷和 sender 對(duì)象所處線(xiàn)程無(wú)關(guān),真正判斷的是發(fā)出信號(hào)這個(gè)動(dòng)作所在的線(xiàn)程
- Qt::DirectConnection:槽函數(shù)會(huì)在信號(hào)發(fā)送的時(shí)候直接被調(diào)用,槽函數(shù)運(yùn)行于信號(hào)發(fā)送者所在線(xiàn)程。效果看上去就像是直接在信號(hào)發(fā)送位置調(diào)用了槽函數(shù)。需要注意的是,在多線(xiàn)程環(huán)境下比較危險(xiǎn),可能會(huì)造成奔潰
- Qt::QueuedConnection:槽函數(shù)在控制回到接收者所在線(xiàn)程的事件循環(huán)時(shí)被調(diào)用,槽函數(shù)運(yùn)行于信號(hào)接收者所在線(xiàn)程。發(fā)送信號(hào)之后,槽函數(shù)不會(huì)立刻被調(diào)用,等到接收者的當(dāng)前函數(shù)執(zhí)行完,進(jìn)入事件循環(huán)之后,槽函數(shù)才會(huì)被調(diào)用。多線(xiàn)程環(huán)境下一般用這個(gè)
- Qt::BlockingQueuedConnection:槽函數(shù)的調(diào)用時(shí)機(jī)與 Qt::QueuedConnection 一致,不過(guò)發(fā)送完信號(hào)后發(fā)送者所在線(xiàn)程會(huì)阻塞,直到槽函數(shù)運(yùn)行完,在多線(xiàn)程間需要同步的場(chǎng)合可能需要這個(gè)。需要注意的是,接收者和發(fā)送者絕對(duì)不能在一個(gè)線(xiàn)程,否則程序會(huì)死鎖
- Qt::UniqueConnection:這個(gè) flag 可以通過(guò)按位或(|)與以上四個(gè)結(jié)合在一起使用。當(dāng)這個(gè)flag設(shè)置時(shí),當(dāng)某個(gè)信號(hào)和槽已經(jīng)連接時(shí),再進(jìn)行重復(fù)的連接就會(huì)失敗,也就是避免了重復(fù)連接
信號(hào)與槽的連接方式
C++ 連接信號(hào)槽 - Qt4 語(yǔ)法
connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(close()));
C++ 連接信號(hào)槽 - Qt5 語(yǔ)法
connect(ui->pushButton, &QPushButton::clicked, this, &MainWindow::close)
C++ 連接信號(hào)槽 - 函數(shù)指針
void(MainWindow:: *buttonClickSlot)() = &MainWindow::onButtonPushed; connect(ui->pushButton, &QPushButton::clicked, this, buttonClickSlot);
C++ 連接信號(hào)槽 - Lambda 表達(dá)式
connect(ui->pushButton, &QPushButton::clicked, this, [=](){ this->close(); });
C++ 信號(hào)連接 QML 的槽
class Test { signals: void sendData(QString str); }
1)如果注冊(cè)的是全局對(duì)象,則需要使用 Connections 連接:
Connections { target: test onSendData: { console.log(str) } }
2)如果注冊(cè)的是類(lèi),則需要先實(shí)例化對(duì)象,之后直接使用 on 接收:
Test { onSendData: { console.log(str) } }
QML 信號(hào)連接 C++ 的槽
#include <QQuickItem> QObject *quitButton = root->findChild<QObject*>("quitButton"); if (quitButton) { QObject::connect(quitButton, SIGNAL(clicked()), &app, SLOT(quit())); }
C++ 調(diào)用 QML 函數(shù)
QObject *changeBtn = root->findChild<QObject*>("objectName"); if (changeBtn) { QMetaObject::invokeMethod(changeBtn, "changeColor"); }
QML 調(diào)用 C++ 函數(shù)
onClicked: { className.test(); }
QML 信號(hào)連接 QML 的槽
// A.qml Rectangle { signal sendData(var data) } // B.qml Rectangle { onSendData: console.log(data) }
到此這篇關(guān)于淺談Qt信號(hào)與槽的各種連接方式的文章就介紹到這了,更多相關(guān)Qt信號(hào)與槽連接內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++按照正態(tài)分布來(lái)排列整型數(shù)組元素
這篇文章主要介紹了C++按照正態(tài)分布來(lái)排列整型數(shù)組元素的相關(guān)資料,需要的朋友可以參考下2016-07-07關(guān)于C++11中限定作用域的枚舉類(lèi)型的問(wèn)題
C++中有兩種類(lèi)型的枚舉:不限定作用域的枚舉類(lèi)型和限定作用域的枚舉類(lèi)型。限定作用域的枚舉類(lèi)型是C++11標(biāo)準(zhǔn)引入的新類(lèi)型,對(duì)C++11中限定作用域的枚舉類(lèi)型相關(guān)知識(shí)感興趣的朋友一起看看吧2022-01-01C語(yǔ)言詳細(xì)分析結(jié)構(gòu)體的內(nèi)存對(duì)齊規(guī)則
C 數(shù)組允許定義可存儲(chǔ)相同類(lèi)型數(shù)據(jù)項(xiàng)的變量,結(jié)構(gòu)是 C 編程中另一種用戶(hù)自定義的可用的數(shù)據(jù)類(lèi)型,它允許你存儲(chǔ)不同類(lèi)型的數(shù)據(jù)項(xiàng),本篇讓我們來(lái)了解C 的結(jié)構(gòu)體內(nèi)存對(duì)齊2022-07-07QT+ffmpeg實(shí)現(xiàn)視頻解析的示例詳解
這篇文章主要為大家詳細(xì)介紹了如何利用QT+ffmpeg實(shí)現(xiàn)視頻解析功能,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Qt有一定幫助,需要的可以參考一下2022-09-09C語(yǔ)言實(shí)現(xiàn)飛機(jī)游戲(豪華版)的示例代碼
在前文中已經(jīng)實(shí)現(xiàn)了基礎(chǔ)版和進(jìn)階版的飛機(jī)游戲,但是存在的問(wèn)題很明顯:已經(jīng)發(fā)射出去的子彈會(huì)隨著飛機(jī)位置的實(shí)時(shí)改變而改變,并且不能實(shí)現(xiàn)連發(fā)。本篇文章將利用數(shù)組進(jìn)一步改進(jìn)空戰(zhàn)游戲,感興趣的可以了解一下2022-10-10C語(yǔ)言詳細(xì)實(shí)現(xiàn)猜拳游戲流程
在學(xué)習(xí)了循環(huán)、分支、和函數(shù)之后,可以寫(xiě)一些簡(jiǎn)單的小游戲來(lái)給自己的編程之路增添一份樂(lè)趣。不僅提升了編碼能力,還可以邊學(xué)邊玩,簡(jiǎn)直妙哉妙哉2022-05-05C++用指針變量作為函數(shù)的參數(shù)接受數(shù)組的值的問(wèn)題詳細(xì)總結(jié)
以下是對(duì)C++中用指針變量作為函數(shù)的參數(shù)接受數(shù)組的值的問(wèn)題進(jìn)行了詳細(xì)的總結(jié)介紹,需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助2013-10-10