QT信號槽連接語法總結


信號槽是 Qt 框架引以為豪的機制之一。

所謂信號槽,實際就是觀察者模式。當某個事件發生之后,比如,按鈕檢測到自己被點擊了一下,它就會發出一個信號(signal)。這種觸發是沒有目的的,類似廣播。如果有對象對這個信號感興趣,它就會使用連接(connect)函數,意思是,將想要處理的信號和自己的一個函數(稱為槽(slot))綁定來處理這個信號。也就是說,當信號發出時,被連接的槽函數會自動被回調。這就類似觀察者模式:當發生了感興趣的事件,某一個操作就會被自動觸發。(這里提一句,Qt 的信號槽使用了額外的處理來實現,並不是 GoF 經典的觀察者模式的實現方式。)

信號和槽是Qt特有的信息傳輸機制,是Qt設計程序的重要基礎,它可以讓互不干擾的對象建立一種聯系。

槽的本質是類的成員函數,其參數可以是任意類型的。和普通C++成員函數幾乎沒有區別,它可以是虛函數;也可以被重載;可以是公有的、保護的、私有的、也可以被其他C++成員函數調用。唯一區別的是:槽可以與信號連接在一起,每當和槽連接的信號被發射的時候,就會調用這個槽

信號與槽的連接:

 C++ Code 
1
2
3
4
5
6
7
8
 
static  QMetaObject::Connection
connect(
    
const  QObject *sender,                           // 參數一:發送者
     const  QMetaMethod &signal,                       // 參數二:信號
     const  QObject *receiver,                         // 參數三:接收者
     const  QMetaMethod &method,                       // 參數四:槽
    Qt::ConnectionType type = Qt::AutoConnection);   // 參數五:連接類型

注意:信號槽要求信號和槽的參數一致,所謂一致,是參數類型一致。如果不一致,允許的情況是,槽函數的參數可以比信號的少,即便如此,槽函數存在的那些參數的順序也必須和信號的前面幾個一致起來。這是因為,你可以在槽函數中選擇忽略信號傳來的數據(也就是槽函數的參數比信號的少),但是不能說信號根本沒有這個數據,你就要在槽函數中使用(就是槽函數的參數比信號的多,這是不允許的)。

信號槽的書寫方式:

  • Qt4的書寫方式

QPushButton* button = new QPushButton("Quit");

connect(button, SIGNAL(clicked()), &a, SLOT(quit()));

這種寫法沒有編譯錯誤,而是在運行時給出錯誤,無疑會增加程序的不穩定性。

只有在 Debug 模式下運行時才會提示槽函數不存在,Release 模式下運行時不會給予任何錯誤提示。

  • Qt5的書寫方式

QPushButton button("Quit");

QObject::connect(&button, &QPushButton::clicked, &app,&QApplication::quit);

  • C++11新方式: Lambda表達式,需要再Pro項目文件中加入 CONFIG += C++ 11

QPushButton* button = new QPushButton("Quit");

connect(button, SIGNAL(clicked()),[=](QString str){

                 qDebug() << str;});

關於Lambda表達式的知識

簡單地說,Lambda表達式就是匿名函數。

以一對方括號[]開始,稱為Lambda表達式的引入符。

引入符后面可以添加Lambda表達式的返回值類型。

接着是參數列表,最后是Lambda表達式的函數體。

引入符描述函數體如何“獲得”外部變量!

所謂“外部變量”指的是函數體以外的變量,這些變量需要在引入符可見的作用域中有定義。

Lambda表達式構成圖解:

  • Capture clause: 捕獲子句
  • Parameter list: 參數列表 可選
  • Mutable specification 可選
  • Exception specification 可選
  • Return type: 返回類型 可選
  • Lambda Body

需要注意的一點:在進行信號槽綁定時,如果有重載,需要對成員函數進行類型轉換,可以使用 C++ 的 static_cast 類型轉換(編譯時進行語法檢查),也可以使用傳統的 C 語言的強制類型轉換(編譯時不進行語法檢查,運行時才檢查),或者 C++11 的 QOverload::of,C++14 的 qOverload:

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
 
QComboBox *comboBox =  new  QComboBox();
comboBox->addItem(
"Michael" );
comboBox->addItem(
"Kobe" );
comboBox->addItem(
"James" );
comboBox->show();

// [1]
QObject::connect(comboBox,
                 
static_cast < void  (QComboBox::*)( int )>(&QComboBox::activated),
                 [](
int  index)
{
    qDebug() << index;
});

// [2]
QObject::connect(comboBox,
                 
static_cast < void  (QComboBox::*)( const  QString &)>(&QComboBox::activated),
                 [](
const  QString &text)
{
    qDebug() << text;
});

// [3]: QOverload<> 里面是參數列表,of() 里面是成員函數地址
QObject::connect(comboBox,
                 QOverload<
const  QString &>::of(&QComboBox::activated),
                 [](
const  QString &text)
{
    qDebug() << text;
});


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM