信號和槽


 1) 信號的定義必須在signals:保留字下,並且不需要實現

2)槽的定義必須在slots:保留字下,需要實現

3)信號和槽通過QObject::connect函數連接

4)當信號被觸發時,槽函數被調用


需要注意的是:

1)信號和槽,是QT的拓展,所以實現信號和槽的類,必須是QObject的子類

2)實現信號和槽的類,必須以宏Q_OBJECT開始

3)連接信號和槽,要用到SIGNAL和SLOT宏,轉換函數為字符串

4)一個信號可以和多個槽連接,槽函數調用的順序是不確定的

5)多個信號可以同時連接一個槽

6)信號可以連接信號,形成信號傳導

7) 當信號與槽函數的參數數量相同時,它們參數類型要完全一致。

  當信號的參數與槽函數的參數數量不同時,只能是信號的參數數量多於槽函數的參數數量,且前面相同數量的參數類型應一致,信號中多余的參數會被忽略。

8)信號和槽都可以重載

9)信號和槽都可以有默認參數

10)槽函數可以像普通函數一樣被調用

11)在槽函數中,調用sender可以獲得信號調用者

 

總結下:

一個類:QObject信號和槽都是這個類的子類

三個宏:Q_OBJECT SIGNAL SLOT

三個保留字:signals, slots, emit

 

在 Qt 5 中,QObject::connect()有五個重載:

 1 //第一個,sender 類型是const QObject *,signal 的類型是const char *,receiver 類型是const QObject *,slot 類型是const char *。這個函數將 signal 和 slot 作為字符串處理
 2 QMetaObject::Connection connect(const QObject *, const char *,
 3                                 const QObject *, const char *,
 4                                 Qt::ConnectionType);
 5 
 6 //第二個,sender 和 receiver 同樣是const QObject *,但是 signal 和 slot 都是const QMetaMethod &
 7 QMetaObject::Connection connect(const QObject *, const QMetaMethod &,
 8                                 const QObject *, const QMetaMethod &,
 9                                 Qt::ConnectionType);
10 
11 //第三個,sender 同樣是const QObject *,signal 和 slot 同樣是const char *,但是卻缺少了 receiver。這個函數其實是將 this 指針作為 receiver
12 QMetaObject::Connection connect(const QObject *, const char *,
13                                 const char *,
14                                 Qt::ConnectionType) const;
15 
16 //第四個,sender 和 receiver 也都存在,都是const QObject *,但是 signal 和 slot 類型則是PointerToMemberFunction。看這個名字就應該知道,這是指向成員函數的指針
17 QMetaObject::Connection connect(const QObject *, PointerToMemberFunction,
18                                 const QObject *, PointerToMemberFunction,
19                                 Qt::ConnectionType)
20 
21 //第五個,前面兩個參數沒有什么不同,最后一個參數是Functor類型。這個類型可以接受 static 函數、全局函數以及 Lambda 表達式
22 QMetaObject::Connection connect(const QObject *, PointerToMemberFunction,
23                                 Functor);

 注意:用lambda表達式在.pro中加入 CONFIG += C++11

 

QT4我們使用了SIGNAL和SLOT這兩個宏,將兩個函數名轉換成了字符串。注意,即使quit()是QApplication的 static 函數,也必須傳入一個對象指針。這也是 Qt 4 的信號槽語法的局限之處。另外,注意到connect()函數的 signal 和 slot 都是接受字符串,因此,不能將全局函數或者 Lambda 表達式傳入connect()。一旦出現連接不成功的情況,Qt 4 是沒有編譯錯誤的(因為一切都是字符串,編譯期是不檢查字符串是否匹配),而是在運行時給出錯誤。這無疑會增加程序的不穩定性。

eg:

 1 #include <QApplication>
 2 #include <QWidget>
 3 #include <QHBoxLayout>
 4 #include <QSlider>
 5 #include <QSpinBox>
 6 
 7 
 8 int main(int argc,char **argv)
 9 {
10     QApplication app(argc,argv);
11 
12     QWidget w;
13     w.setWindowTitle("Enter your age");
14 
15     QSpinBox *spinbox = new QSpinBox(&w);
16     QSlider *slider = new QSlider(Qt::Horizontal,&w);
17     spinbox->setRange(0,130);
18     slider->setRange(0,130);
19 
20     /*
21     //QT4的寫法,使用SIGNAL和SLOT,
22     QObject::connect(slider,SIGNAL(valueChanged(int)),spinbox,SLOT(setValue(int)));
23     QObject::connect(spinbox,SIGNAL(valueChanged(int)),slider,SLOT(setValue(int)));
24     */
25 
26     //QT5的寫法,用指向成員函數的指針
27     QObject::connect(slider,&QSlider::valueChanged,spinbox,&QSpinBox::setValue);
28 
29     //如果不加下面一行會報錯,原因是QSpinBox的確有兩個信號:void valueChanged(int)和void valueChanged(const QString &)
30     //使用 Qt 4 的SIGNAL和SLOT宏,因為這兩個宏已經指定了參數信息,所以不存在這個問題,解決方法使用函數指針顯式指定使用哪一個信號
31     void(QSpinBox:: *spinBoxSignal)(int) = &QSpinBox::valueChanged;
32     QObject::connect(spinbox,spinBoxSignal,slider,&QSlider::setValue);
33 
34 
35     spinbox->setValue(44);
36 
37     QHBoxLayout *layout = new QHBoxLayout;
38     layout->addWidget(spinbox);
39     layout->addWidget(slider);
40     w.setLayout(layout);
41     w.show();
42 
43     return app.exec();
44 }

 


免責聲明!

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



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