Qt 5——信號和槽機制

1.概念

信號槽是 Qt 框架引以爲豪的機制之一。所謂信號槽,實際就是觀察者模式。當某個事件發生之後,比如,按鈕檢測到自己被點擊了一下,它就會發出一個信號(signal)。這種發出是沒有目的的,類似廣播。如果有對象對這個信號感興趣,它就會使用連接(connect)函數,意思是,將想要處理的信號和自己的一個函數(稱爲槽(slot))綁定來處理這個信號。也就是說,當信號發出被連接的槽函數會自動被回調。這就類似觀察者模式:當發生了感興趣的事件,某一個操作就會被自動觸發。

在這裏插入圖片描述

2.系統自帶的信號和槽

下面我們完成一個小功能,上面我們已經學習了按鈕的創建,但是還沒有體現出按鈕的功能,按鈕最大的功能也就是點擊後觸發一些事情,比如我們點擊按鈕,就把當前的窗口給關閉掉,那麼在Qt中,這樣的功能如何實現呢?
其實無法兩行代碼就可以搞定了,我們看下面的代碼

QPushButton * quitBtn = new QPushButton("關閉窗口",this);
  connect(quitBtn,&QPushButton::clicked,this,&MyWidget::close);

第一行是創建一個關閉按鈕,這個之前已經學過,第二行就是核心了,也就是信號槽的使用方式
connect()函數最常用的一般形式:

connect(sender, signal, receiver, slot);

參數解釋:

  1. sender:發出信號的對象
  2. signal:發送對象發出的信號
  3. receiver:接收信號的對象
  4. slot:接收對象在接收到信號之後所需要調用的函數(槽函數)

那麼系統自帶的信號和槽通常如何查找呢,這個就需要利用幫助文檔了,在幫助文檔中比如我們上面的按鈕的點擊信號,在幫助文檔中輸入QPushButton,首先我們可以在Contents中尋找關鍵字 signals,信號的意思,但是我們發現並沒有找到,這時候我們應該想到也許這個信號的被父類繼承下來的,因此我們去他的父類QAbstractButton中就可以找到該關鍵字,點擊signals索引到系統自帶的信號有如下幾個

在這裏插入圖片描述
這裏的clicked就是我們要找到,槽函數的尋找方式和信號一樣,只不過他的關鍵字是slot。

3. 自定義信號和槽

使用connect()可以讓我們連接系統提供的信號和槽。但是,Qt 的信號槽機制並不僅僅是使用系統提供的那部分,還會允許我們自己設計自己的信號和槽。
下面我們看看使用 Qt 的信號槽:

首先定義一個學生類和老師類:
	老師類中聲明信號 餓了 hungry
signals:
  void hungury();
	學生類中聲明槽   請客 treat
	public slots:
       void treat();
	在窗口中聲明一個公共方法下課,這個方法的調用會觸發老師餓了這個信號,而響應槽函數學生請客
	void MyWidget::ClassIsOver()
{
    //發送信號
    emit teacher->hungury();
}
	學生響應了槽函數,並且打印信息
//自定義槽函數 實現
void Student::eat()
{
       qDebug() << "該喫飯了!";
}
在窗口中連接信號槽
    teacher = new Teacher(this);
    student = new Student(this);

    connect(teacher,&Teacher::hungury,student,&Student::treat);
並且調用下課函數,測試打印出 “該喫飯了”

自定義的信號 hungry帶參數,需要提供重載的自定義信號和 自定義槽
void hungury(QString name);  自定義信號
void treat(QString name );    自定義槽
但是由於有兩個重名的自定義信號和自定義的槽,直接連接會報錯,所以需要利用函數指針來指向函數地址, 然後在做連接
void (Teacher:: * teacherSingal)(QString) = &Teacher::hungury;
void (Student:: * studentSlot)(QString) = &Student::treat;
connect(teacher,teacherSingal,student,studentSlot);

自定義信號槽需要注意的事項:

  • 發送者和接收者都需要是QObject的子類(當然,槽函數是全局函數、Lambda 表達式等無需接收者的時候除外);
  • 信號和槽函數返回值是 void
  • 信號只需要聲明,不需要實現
  • 槽函數需要聲明也需要實現
  • 槽函數是普通的成員函數,作爲成員函數,會受到 public、private、protected 的影響;
  • 使用 emit 在恰當的位置發送信號;
  • 使用connect()函數連接信號和槽。
  • 任何成員函數、static 函數、全局函數和 Lambda 表達式都可以作爲槽函數
  • 信號槽要求信號和槽的參數一致,所謂一致,是參數類型一致。
  • 如果信號和槽的參數不一致,允許的情況是,槽函數的參數可以比信號的少,即便如此,槽函數存在的那些參數的順序也必須和信號的前面幾個一致起來。這是因爲,你可以在槽函數中選擇忽略信號傳來的數據(也就是槽函數的參數比信號的少)。

4.信號槽的拓展

  • 一個信號可以和多個槽相連
    如果是這種情況,這些槽會一個接一個的被調用,但是它們的調用順序是不確定的。
  • 多個信號可以連接到一個槽
    只要任意一個信號發出,這個槽就會被調用。
  • 一個信號可以連接到另外的一個信號
    當第一個信號發出時,第二個信號被髮出。除此之外,這種信號-信號的形式和信號-槽的形式沒有什麼區別。
  • 槽可以被取消鏈接
    這種情況並不經常出現,因爲當一個對象delete之後,Qt自動取消所有連接到這個對象上面的槽。
  • 信號槽可以斷開
    利用disconnect關鍵字是可以斷開信號槽的
  • 使用Lambda 表達式
    在使用 Qt 5 的時候,能夠支持 Qt 5 的編譯器都是支持 Lambda 表達式的。
    在連接信號和槽的時候,槽函數可以使用Lambda表達式的方式進行處理。後面我們會詳細介紹什麼是Lambda表達式

5.下面是信號與槽的簡單代碼示例:

https://download.csdn.net/download/weixin_45525272/12535637

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章