1. 程式人生 > >Qt 自定義訊號與槽

Qt 自定義訊號與槽

注 物件與槽理解

    //第一個引數lineEdit是激發事件物件,訊號中的方法必須在物件中存在,並在物件類標頭檔案signals下定義,
    //第二個引數訊號,
    //第三個引數this是槽方法所屬類的物件,且必須在物件類的標頭檔案的slots下定義
    //第四個引數槽方法類,槽 方法
    connect(lineEdit,SIGNAL(textChanged(QString)),this,SLOT(showArea()));

使用自定義的訊號和槽,需要注意以下幾點: 
1、類的宣告和實現分別放在.h和.cpp檔案中; 
2、類宣告中包含Q_OBJECT巨集; 
3、訊號只要宣告不要設計其的實現函式; 

4、發射訊號用emit關鍵字; 
5、自定義槽的實現與普通成員函式的實現一樣。 

6、訊號和槽方法必須在類的標頭檔案中定義

本文所示程式碼在windows xp + MingW3.4.2+ eclipse3.4+CDT5.0版本中除錯通過
    QT系統為我們提供功能非常全面訊號處理機制,它的內製訊號和槽已經非常全面,因此大多數情況下,我們不需要自己設計訊號和槽,但是有些時候,我們可能需要設計一些獨特的訊號和槽,來滿足程式的需求。QT的核心機制訊號和槽是獨立於C++的,一般C++設計處理如按鈕點選等方法,多采用回撥函式,而回調函式設計上的複雜,雖然執行效率相對於QT訊號與槽要高,但是其導制容易出錯。況且在日常應用程式設計中來說,這種高效率相差不成比例,因此QT採用自己獨門設計,來高效的程式設計。本文也同樣倡導大家使用訊號與槽。


    如何才能設計自己的訊號和槽呢,閱讀完本節您將會輕鬆實現自己的需求。
    在建立訊號和槽之前首先大家需要建立三個檔案:類申明檔案(yourclass.h),類實現檔案(youclass.cpp),程式主體檔案(main.cpp)。
    請看下面的例子,假設我們需要一個來處理文字框的內容的程式,程式主介面有兩個按鈕,當們點選按鈕[Modify]時,文字框內容被改為“jingjing”。
1、自定義槽:
    按鈕點選訊號clilcked()通過繼承已經存在,因此我們暫時不需要定義這個訊號。那麼我們要改變文字框內容,就需要自己定義一個槽,來響應點選訊號。
    示例程式碼(類申明檔案 yourclass.h):

複製程式碼
  1. #ifndef YOURCLASS_H_
  2.     #define YOURCLASS_H_
  3.     #include <QWidget>                        //QT視窗應用程式需要包含的檔案
  4.     #include <QPushButton>                    //製作按鈕時,需要包含
  5.     #include <QLineEdit>                      //製作文字框時,需要包含
  6.     class MyMainWindows:public QWidget        //申明一個MyMainWindows類,這個類用於實現窗體
  7.     {                                                         
  8.      Q_OBJECT                            //Q_OBJECT是在定製訊號和槽和必須包含的一條巨集語句
  9.     public:                                                   
  10.         MyMainWindows();                    //類建構函式(用於實現程式的主體部份)
  11.     public slots:                              //所有的槽函式都必須申明public slots語句內
  12.           void SlotTest();                    //這個槽函式用於顯應點選按鈕時改變文字框內容
  13.     private:
  14.         QPushButton * pb;                    //申請一個按鈕QPushButton
  15.         QLineEdit * ledit;                      //申請一個文字框ledit
  16.     };
  17.     #endif /* YOURClASS_H_ */   

    在上面的示例程式碼中,我們申明瞭一視窗應用程式類檔案,它的功能是申明程式所需要全部元素資訊。在這個類中,我們申明瞭自己的槽SlotTest()函式,來響應按鈕點選的訊號。如下所示:
複製程式碼
  1. public slots:                              //所有的槽函式都必須申明public slots語句內
  2.           void SlotTest();                    //這個槽函式用於顯應點選按鈕時改變文字框內容

    正如程式碼中註釋說明,在自定義槽和訊號是有兩點是至關重要的:
    第一點:所有的槽函式都需要包含在public slots語句下面。它的申明和類的公有函式方法pulic是類似的。如果你有多個槽函式,只要需要一一列出即可。
    第二點;在類的檔案開始部份應含Q_OBJECT巨集語句,請記住它不需要標點符號,所以不要加[;]符號。所有的QT自定義槽和訊號都需要有它的存在。
    下面是製作第二個檔案:類實現檔案yourclass.cpp。在這個檔案用於yourclass.h中申明的元素實現部份。
    示例程式碼(類實現檔案yourclass.cpp)
複製程式碼
  1. #include "yourclass.h"                                  //包含yourclass.h類申明檔案
  2. MyMainWindows::MyMainWindows()                    //實現建構函式
  3. {
  4.   setGeometry(90,90,300,200);                          //繪製主窗體,大小為300X200
  5.   pb = new QPushButton("Modify",this);                  //實現pb按鈕,被設計其名字為Modify
  6.   pb->setGeometry(10,10,100,20);                        //繪製pb按鈕的位置(10,10)和大小(100,20)
  7.   ledit = new QLineEdit("what's your name",this);          //實現ledit檔案框,其內容為what's your name
  8.   ledit->setGeometry(10,30,200,150);                    //繪製ledit檔案框位置(10,30)和大小(200,150)
  9.   connect(pb,SIGNAL(clicked()),this,SLOT(SlotTest()));    //連線pb按鈕的點選clicked()訊號和自定義槽SlotTest()
  10. }
  11. void MyMainWindows::SlotTest()                        //自定義槽函式的實現方法,重置文字框的內容
  12. {
  13.   ledit->setText("jingjing");                            //“jingjing”為點選按鈕Modify後的內容
  14. }

在yourclass.cpp中,我們實現了程式的全部功能,程式的執行還需要有一個入口。它的主體部分mian.cpp。
複製程式碼
  1. #include <QApplication>              //所有QT應用程式都要包含QApplication標頭檔案
  2. #include "yourclass.h"                //包含類定義檔案yourclass.h
  3. int main(int argc,char * argv[])
  4. {
  5.   QApplication app(argc,argv);        //申明一個QT應用程式對像app
  6.   MyMainWindows w;                      //申明我們實現MyMainWindows窗體對像 w.
  7.   w.show();                                //顯示這個w 窗體
  8.   return app.exec();
  9. }

程式編譯完成後執行當點選Modify按鈕,文字內容what's your name 被修改為jingjing
2、自定義訊號
    在上例中,我們瞭解了怎樣來實現自己的槽函式,在下文中我們將介紹怎麼實現自己的訊號。QT訊號的申明與實現,相對QT槽函式來說,要更加容易一些。它相當於一系列函式原型。不需要有具體實現處理內容。在上文中,我們是通過點選clicked()這個訊號,來連線槽函式SlotTest(),並達到修改文字框的內容。本例中,我們將在窗體新增一個文字標籤label,然後在槽函式SlotTest()中測試label內容是否發生變化,如果發生了變化,就引發訊號SigTest()。該訊號連線到槽函式SlotTest2(),將文字框內容修改為"SigSig"。
    下面為實現檔案:
    請開啟上節中的yourclass.h檔案,在程式碼加入一個槽函式SlotTest2(),和一個訊號SigTest()。紅色程式碼為新增加內容,如下所示:
複製程式碼
  1. #ifndef YOURCLASS_H_
  2.     #define YOURCLASS_H_
  3.     #include <QWidget>                        //QT視窗應用程式需要包含的檔案
  4.     #include <QPushButton>                    //製作按鈕時,需要包含
  5.     #include <QLineEdit>                      //製作文字框時,需要包含
  6.     #include <QLabel>                        //製作文字標籤時,需要包含
  7.     class MyMainWindows:public QWidget        //申明一個MyMainWindows類,這個類用於實現窗體
  8.     {                                                         
  9.      Q_OBJECT                            //Q_OBJECT是在定製訊號和槽和必須包含的一條巨集語句
  10.     public:                                                   
  11.         MyMainWindows();                    //類建構函式(用於實現程式的主體部份)
  12.     public slots:                              //所有的槽函式都必須申明public slots語句內
  13.           void SlotTest();                    //這個槽函式用於顯應點選按鈕時改變文字框內容
  14.           void SlotTest2();                    //新增加槽函式,用於將文字框內容改為SigSig
  15.   private:
  16.         QPushButton * pb;                    //申請一個按鈕QPushButton
  17.         QLineEdit * ledit;                      //申請一個文字框ledit
  18.         QLabel * label;                        //申請一個文字標籤label
  19.      Signals:                                //所有訊號都需要申明在signals語句內
  20.        void SigTest()                        //新增加訊號SigTest()。
  21.     }; 
  22.     #endif /* YOURClASS_H_ */   

    在這個例子中,我們加入了自定義的訊號SigTest()。在QT中訊號的申請方法是,在類中加入signals(訊號)語句。然後在語句後面定義自己的訊號函式就可以了。有趣的是訊號的定義並不需要具體實現,它就像一系列函式原型一樣。你只需要申請就可以了。本例中,我們申請了一個不帶有任何引數的訊號SigTest()。在下文中我們將用這個訊號來實現文字框內容變化。
    在窗體上要繪製文字標籤,就必須加入<QLabel>標頭檔案。其次我們在程式碼中新增加了一個槽SlotTest2()函式和一個訊號SigTest()函式,並通過connect()函式連線。
    程式碼如下所示(yourclass.cpp):
複製程式碼
  1. #include "yourclass.h"
  2. MyMainWindows::MyMainWindows()
  3. {
  4.   setGeometry(90,90,300,200);
  5.   pb = new QPushButton("Modify",this);
  6.   pb->setGeometry(10,10,100,20);
  7.   ledit = new QLineEdit("what's your name",this);
  8.   ledit->setGeometry(10,30,200,150);
  9.   label = new QLabel("My MeMe",this);                //實現一個文字標籤label,並將其內容初使為:My MeMe
  10.   label->setGeometry(115,10,100,20);
  11.   connect(pb,SIGNAL(clicked()),this,SLOT(SlotTest())); 
  12.   connect(this,SIGNAL(SigTest()),this,SLOT(SlotTest2())); //連線自定義訊號SigTest  ()和SlotTest2()槽函式
  13. }
  14. void MyMainWindows::SlotTest()                      //訊號1
  15. {
  16.   ledit->setText("jingjing");
  17.   label->setText("TTT");                          //將文字標籤label內容設定為TTT文字
  18.   if(label->text() != "My MeMe")
  19.     {
  20.       emit SigTest();
  21.     }
  22. }
  23. void MyMainWindows::SlotTest2()              //訊號2
  24. {
  25.   ledit->setText("SigSig");  //設定文字框內容為SigSig
  26. }

    從上面程式碼中可以看出,首先我們在MyMainWindows()主窗體類建構函式中加入了
複製程式碼
  1. label = new QLabel("My MeMe",this);             
  2.        label->setGeometry(115,10,100,20);

    Label文字標籤的初使內容為My MeMe。其位置為窗體的(115,10),大小為(100,20),我們在上一事例中講過的槽函式SlotTest()中新加入了對文字標籤的檢測,來達到對我們自定義訊號SigTest()觸發。如下所示:
複製程式碼
  1. void MyMainWindows::SlotTest()                      //訊號1
  2. {
  3.   ledit->setText("jingjing");
  4.   label->setText("TTT");                          //將文字標籤label內容設定為TTT文字
  5.   if(label->text() != "My MeMe")
  6.     {
  7.       emit SigTest();
  8.     }
  9. }
  10. void MyMainWindows::SlotTest2()              //訊號2
  11. {
  12.   ledit->setText("SigSig");  //設定文字框內容為SigSig
  13. }

    如程式碼所示當SlotTest()槽函式被呼叫時,首先將ledit文字框內容設為jingjing,並把label文字標籤內容設為TTT,然後此時我們檢測label的內容是不是還為它的初使內容My MeMe,如果不是,則引發我們自定義的SigTest()訊號。請注意程式碼中emit(發射)關鍵字,做為QT訊號與槽機制來說,emit的作用就是將訊號發出來的意思。也就是說,當我們類申明檔案中定義了一個訊號時,如果要使用這個訊號,只需在訊號語句前面加上emit關鍵字就可以了。
    而在SlotTest2()槽函式中,我們把文字框ledit的內容設為:SigSig。也就是當SlotTest2()槽函式被呼叫時就又會把ledit中內容修改為SigSig。在本事例中,我們用SigTest()訊號來連線SlotTest2()這個槽,也就是說當SigTest()訊號被觸發時,就會將文字框的內容修改為:SigSig。程式碼如下:
複製程式碼
  1. connect(this,SIGNAL(SigTest()),this,SLOT(SlotTest2()));


    現在讓我們把上例中的Main.cpp檔案放到一起,進行編譯
    當第一次點選[Modify]按鈕時,程式首先產生一個訊號clicked(),而這個訊號將導致SlotTest()槽被執行,文字框的內容首先被修改為jingjing,然後label文字標籤的內容被修改為TTT,隨後在SlotTest()語句發現label的內容不是My MeMe,因此向外發射訊號SigTest()。而SigTest()訊號與SlotTest2()槽連線,因此導致SlotTest2()槽函式被呼叫,它又將文字框內容修改為了SigSig。因此當我們點選Modify時,文字框內容最終會變為SigSig文字。

相關推薦

Qt 定義訊號

注 物件與槽理解 //第一個引數lineEdit是激發事件物件,訊號中的方法必須在物件中存在,並在物件類標頭檔案signals下定義, //第二個引數訊號, //第三個引數this是槽方法所屬類的物件,且必須在物件類的標頭檔案的slots下定義

【PyQt5-Qt Designer】pyqtSignal()-高階定義訊號

PyQt 5訊號與槽的幾種高階玩法 參考:http://www.broadview.com.cn/article/824 from PyQt5.QtCore import QObject , pyqtSignal class CustSignal(QObject): #宣告無引數的訊號

170329 PyQt5 定義訊號

1625-5 王子昂 總結《2017年3月28日》 【連續第178天總結】 A.PyQt5資料傳送、處理及訊號與槽的練習 B.今天終於把手頭上的事都搞完了 資料傳輸都是很瑣碎的東西,前幾天也熟悉過了,

QT 定義函式 定義訊號

在QT中自定義函式,訊號,槽基本上都是在基類上派生時設計的 這裡分兩種情況討論 一,程式碼模式 通過.H和.cpp設計介面佈局,並通過派生設計自定義的函式,訊號,槽 二,視覺化設計模式 1,設計工具設計介面 2,新建類繼承上面的介面,並設計自定義函

Qt 筆記:訊號的連線方式

深入訊號與槽的連線方式 -Qt::DirectConnection(立即呼叫) -Qt::QueuedConnection(非同步呼叫) -Qt::BlockingQueuedConnection(同步呼叫) -Qt::AutoConnection(預設連線) -Q

Qt-登入介面訊號函式

Qt訊號與槽函式可以實現任意兩個Qt類的物件之間進行通訊,比如登入類QtLoginWin 與介面上的登入按鈕loginBt 當點選按鈕的時候會發送clicked訊號,這樣就可以與QtLoginWin的槽函式關聯進行通訊如下圖: 把控制元件的名字分別修改為 使用者

Qt程式設計之訊號-------unresolved external symbol "public: virtual struct QMetaObject const * __thiscall XX::metaObject(void)const

原因是加入Q_OBJECT這個macro的類,被編譯的時候就要用到moc這個命令,所以在VS2010中,沒有加入此命令的應用,當然會出錯了。所以解決辦法是加,或者如果你不使用訊號槽可以直接刪除。 當要在GUI中用到訊號與槽,就需在.h檔案中的類裡寫入Q_OBJECT巨集。而任何含有Q_Object的類都

Qt 中的訊號,連線日誌庫QsLog,在介面上顯示出日誌資訊

新建一個基於QWidget的工程,在介面上新增一個QTextBrowser控制元件,用來在介面顯示日誌資訊。 在pro檔案中新增QsLog的標頭檔案和lib庫 INCLUDEPATH += include/QsLog.h \ inc

定義型別用於訊號之間的傳輸

應用場景: 使用訊號和槽的時候可以傳遞引數,但Qt只支援預設的型別,不支援自定義型別, 如果要使用自定義型別,需要通過2步來實現 第一步:在定義類的標頭檔案的尾部新增程式碼: Q_DECLARE_METATYPE(Block); class Block { public: Blo

QT 如何繫結定義訊號

一 原理qt中不能繫結非基本型別的訊號槽,例如自己的結構體等。二 方法此時就需要我們用qt自帶的方法註冊一下這個訊號槽,例子:有如下一個自定義引數的訊號 void drawInfo(SDRAWINGDATA &drawInfo , DATATYPE type); 會報

QT學習day02---圖形介面、對話方塊、訊號

一、QT圖形介面 ①QT座標軸 起點:左上角 X:橫軸 Y:縱軸 ②QWidget、QDialog、QMainWindow的異同點 QWidget:視窗為空,什麼內容都沒有 QMainWindow:含有選單欄,狀態列,工具欄等…已經包含了QWidget QDialog:對話方塊(

QT多執行緒中,物件訊號連線不上的解決辦法

1、在接收者建立執行緒中,把接收者移動到主執行緒中: pReceiverObj->moveToThread(QApplication::instance()->thread()); 2、這樣傳送訊號的時候,就會在主執行緒事件佇列處理中來處理了。 把connect的最

QT學習記錄1(訊號

使用,學習QT的背景 剛入職新公司,工作是嵌入式軟體,工作內容包括使用QT進行一些軟體的開發等,以前沒有接觸過QT,特意建立第一篇部落格,用作QT的學習過程記錄 入職後,公司前輩要求使用QT寫一個軟體,接收硬體裝置傳回的資料並顯示,同時軟體可以對裝置的工作方式進行設定,使用TCP通訊協議。

QT使用訊號注意事項

QT使用訊號與槽注意事項 如需轉載請標明出處:http://blog.csdn.net/itas109 QQ技術交流群:129518033 目錄 文章目錄 QT使用訊號與槽注意事項 @[toc] 前言

QT學習之路---訊號問題解析

前兩天用到了QT的訊號與槽這個機制,剛開始發射訊號的時候,我是這麼寫的語句 connect(sender,SINGAL(),receiver,SLOT()) 由於我用的是QT 5.11這個本,從網上查到的例子來說,大部分都是以上那個形式,也沒有問題,而實際上在QT5.11版本上,向下面這樣寫

實現自己的訊號機制-借鑑Qt

如果對Qt的訊號與槽機制不太理解可以檢視以下網址: http://blog.csdn.net/fuyunzhishang1/article/details/48345381 該博主講的十分的清楚。 最近我自己在做基於嵌入式的GUI,重構了好幾遍總覺得自己的訊息機制很繁瑣,直到自己看到了Q

QT:moveToThread訊號機制的第五個引數Qt::ConnectionType

原來對QThread的理解,就是重寫run(),曾經還一度搞不明白,到底它的槽屬於主執行緒還是子執行緒。後來學了MFC,一度覺得MFC的機制比較人性化,起碼有工作執行緒和介面執行緒的用法,而不像QThread只有run是真正活在子執行緒裡面的。而直到今天再次研究QThrea

Pyqt/Qt訊號的理解(一)

訊號與槽有三種使用方法:內建訊號與槽,自定義訊號與槽和裝飾器的訊號與槽。 內建訊號與槽 內建訊號與槽是指在發射訊號時,使用視窗控制元件的函式,而不是自定義的函式,可通過QObject.signal.connect將一個QObject的訊號連線到另一個QO

QT 訊號在不同執行緒不能連線的問題

QObject::connect: Cannot queue arguments of type 'ERROR_LEVEL'  (Make sure 'ERROR_LEVEL' is registered using qRegisterMetaType().) 其中ER

PyQt5筆記之Qt Designer定義訊號emit及傳參

from PyQt5 import QtWidgets,QtCore  from untitled import Ui_Form  import  time  class MyWindow(QtWidgets.QWidget,Ui_Form):      _signal=Qt