簡介
信號槽是 Qt 框架引以為豪的機制之一。當用戶觸發某個事件時,就會發出一個信號(signal),這種發出是沒有目的的,類似廣播。如果有對象對這個信號感興趣,它就會連接(connect)綁定一個函數(稱為槽slot)來處理這個信號。也就是說當信號發出時,被連接的槽函數會自動被回調。這有點類似與開發模式中的觀察者模式,即當發生了感興趣的事件,某一個操作就會被自動觸發
信號和槽是Qt特有的信息傳輸機制,是Qt設計程序的重要基礎,它可以讓互不干擾的對象建立一種聯系。槽的本質是類的成員函數,其參數可以是任意類型的。和普通C++成員函數幾乎沒有區別,它可以是虛函數,也可以被重載。可以是公有的、保護的、私有的、也可以被其他C++成員函數調用。唯一區別的是:槽可以與信號連接在一起,每當和槽連接的信號被發射的時候,就會調用這個槽
連接信號槽 connect 函數的第五個參數
connect 函數原型如下:
[static] QMetaObject::Connection QObject::connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type = Qt::AutoConnection)
ConnectionType 是一個定義在 Qt namespace 中的一個枚舉,具體內容如下:
1
2
3
4
5
6
7
|
enum ConnectionType { AutoConnection, DirectConnection, QueuedConnection, BlockingQueuedConnection, UniqueConnection = 0x80 }; |
- Qt::AutoConnection:默認值。根據 sender 和 receiver 所處線程在信號發出時作出判斷。如果在同一線程則使用 Qt::DirectConnection 連接,否則使用 Qt :: QueuedConnection 連接。需要注意的是,這個判斷和 sender 對象所處線程無關,真正判斷的是發出信號這個動作所在的線程
- Qt::DirectConnection:槽函數會在信號發送的時候直接被調用,槽函數運行于信號發送者所在線程。效果看上去就像是直接在信號發送位置調用了槽函數。需要注意的是,在多線程環境下比較危險,可能會造成奔潰
- Qt::QueuedConnection:槽函數在控制回到接收者所在線程的事件循環時被調用,槽函數運行于信號接收者所在線程。發送信號之后,槽函數不會立刻被調用,等到接收者的當前函數執行完,進入事件循環之后,槽函數才會被調用。多線程環境下一般用這個
- Qt::BlockingQueuedConnection:槽函數的調用時機與 Qt::QueuedConnection 一致,不過發送完信號后發送者所在線程會阻塞,直到槽函數運行完,在多線程間需要同步的場合可能需要這個。需要注意的是,接收者和發送者絕對不能在一個線程,否則程序會死鎖
- Qt::UniqueConnection:這個 flag 可以通過按位或(|)與以上四個結合在一起使用。當這個flag設置時,當某個信號和槽已經連接時,再進行重復的連接就會失敗,也就是避免了重復連接
信號與槽的連接方式
C++ 連接信號槽 - Qt4 語法
1
|
connect(ui->pushButton, SIGNAL(clicked()), this , SLOT(close())); |
C++ 連接信號槽 - Qt5 語法
1
|
connect(ui->pushButton, &QPushButton::clicked, this , &MainWindow::close) |
C++ 連接信號槽 - 函數指針
1
2
|
void (MainWindow:: *buttonClickSlot)() = &MainWindow::onButtonPushed; connect(ui->pushButton, &QPushButton::clicked, this , buttonClickSlot); |
C++ 連接信號槽 - Lambda 表達式
1
|
connect(ui->pushButton, &QPushButton::clicked, this , [=](){ this ->close(); }); |
C++ 信號連接 QML 的槽
1
2
3
4
|
class Test { signals: void sendData(QString str); } |
1)如果注冊的是全局對象,則需要使用 Connections 連接:
1
2
3
4
5
6
|
Connections { target: test onSendData: { console. log (str) } } |
2)如果注冊的是類,則需要先實例化對象,之后直接使用 on 接收:
1
2
3
4
5
|
Test { onSendData: { console. log (str) } } |
QML 信號連接 C++ 的槽
1
2
3
4
5
|
#include <QQuickItem> QObject *quitButton = root->findChild<QObject*>( "quitButton" ); if (quitButton) { QObject::connect(quitButton, SIGNAL(clicked()), &app, SLOT(quit())); } |
C++ 調用 QML 函數
1
2
3
4
5
|
QObject *changeBtn = root->findChild<QObject*>( "objectName" ); if (changeBtn) { QMetaObject::invokeMethod(changeBtn, "changeColor" ); } |
QML 調用 C++ 函數
1
2
3
4
|
onClicked: { className.test(); } |
QML 信號連接 QML 的槽
1
2
3
4
5
6
7
8
9
|
// A.qml Rectangle { signal sendData(var data) } // B.qml Rectangle { onSendData: console. log (data) } |
到此這篇關于淺談Qt信號與槽的各種連接方式的文章就介紹到這了,更多相關Qt信號與槽連接內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!
原文鏈接:https://blog.csdn.net/qq_34139994/article/details/120034393