QT信號和槽機制

      網友投稿 999 2025-04-01

      首先給大家推薦一個學習C語言/C++ 的github,分享C語言/C入門、學習路線、電子書籍推薦與下載、視頻推薦、小項目、干貨文章、筆試面試、C語言/C++ 規范、開源項目等。

      地址:C語言/C++學習平臺

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

      1.1 系統自帶的信號和槽

      下面我們完成一個小功能,上面我們已經學習了按鈕的創建,但是還沒有體現出按鈕的功能,按鈕最大的功能也就是點擊后觸發一些事情,比如我們點擊按鈕,就把當前的窗口給關閉掉,那么在Qt中,這樣的功能如何實現呢?

      其實無法兩行代碼就可以搞定了,我們看下面的代碼

      QPushButton * quitBtn = new QPushButton("關閉窗口",this);

      connect(quitBtn,&QPushButton::clicked,this,&MyWidget::close);

      第一行是創建一個關閉按鈕,這個之前已經學過,第二行就是核心了,也就是信號槽的使用方式

      connect()函數最常用的一般形式:

      connect(sender, signal, receiver, slot);

      參數解釋:

      sender:發出信號的對象

      signal:發送對象發出的信號

      receiver:接收信號的對象

      slot:接收對象在接收到信號之后所需要調用的函數(槽函數)

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

      這里的clicked就是我們要找到,槽函數的尋找方式和信號一樣,只不過他的關鍵字是slot。

      1.2 自定義信號和槽

      使用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 表達式都可以作為槽函數

      信號槽要求信號和槽的參數一致,所謂一致,是參數類型一致。

      如果信號和槽的參數不一致,允許的情況是,槽函數的參數可以比信號的少,即便如此,槽函數存在的那些參數的順序也必須和信號的前面幾個一致起來。這是因為,你可以在槽函數中選擇忽略信號傳來的數據(也就是槽函數的參數比信號的少)。

      1.3信號槽的拓展

      一個信號可以和多個槽相連

      如果是這種情況,這些槽會一個接一個的被調用,但是它們的調用順序是不確定的。

      QT信號和槽機制

      多個信號可以連接到一個槽

      只要任意一個信號發出,這個槽就會被調用。

      一個信號可以連接到另外的一個信號

      當第一個信號發出時,第二個信號被發出。除此之外,這種信號-信號的形式和信號-槽的形式沒有什么區別。

      槽可以被取消鏈接

      這種情況并不經常出現,因為當一個對象delete之后,Qt自動取消所有連接到這個對象上面的槽。

      信號槽可以斷開

      利用disconnect關鍵字是可以斷開信號槽的

      使用Lambda 表達式

      在使用 Qt 5 的時候,能夠支持 Qt 5 的編譯器都是支持 Lambda 表達式的。

      在連接信號和槽的時候,槽函數可以使用Lambda表達式的方式進行處理。后面我們會詳細介紹什么是Lambda表達式

      1.4 Qt4版本的信號槽寫法

      connect(zt,SIGNAL(hungry(QString)),st,SLOT(treat(QString)));

      這里使用了SIGNAL和SLOT這兩個宏,將兩個函數名轉換成了字符串。注意到connect()函數的 signal 和 slot 都是接受字符串,一旦出現連接不成功的情況,Qt4是沒有編譯錯誤的(因為一切都是字符串,編譯期是不檢查字符串是否匹配),而是在運行時給出錯誤。這無疑會增加程序的不穩定性。

      Qt5在語法上完全兼容Qt4,而反之是不可以的。

      1.5 Lambda表達式

      C++11中的Lambda表達式用于定義并創建匿名的函數對象,以簡化編程工作。首先看一下Lambda表達式的基本構成:

      [capture](parameters) mutable ->return-type

      {

      statement

      }

      [函數對象參數](操作符重載函數參數)mutable ->返回值{函數體}

      ① 函數對象參數;

      [],標識一個Lambda的開始,這部分必須存在,不能省略。函數對象參數是傳遞給編譯器自動生成的函數對象類的構造函數的。函數對象參數只能使用那些到定義Lambda為止時Lambda所在作用范圍內可見的局部變量(包括Lambda所在類的this)。函數對象參數有以下形式:

      空。沒有使用任何函數對象參數。

      =。函數體內可以使用Lambda所在作用范圍內所有可見的局部變量(包括Lambda所在類的this),并且是值傳遞方式(相當于編譯器自動為我們按值傳遞了所有局部變量)。

      &。函數體內可以使用Lambda所在作用范圍內所有可見的局部變量(包括Lambda所在類的this),并且是引用傳遞方式(相當于編譯器自動為我們按引用傳遞了所有局部變量)。

      this。函數體內可以使用Lambda所在類中的成員變量。

      a。將a按值進行傳遞。按值進行傳遞時,函數體內不能修改傳遞進來的a的拷貝,因為默認情況下函數是const的。要修改傳遞進來的a的拷貝,可以添加mutable修飾符

      &a。將a按引用進行傳遞。

      a, &b。將a按值進行傳遞,b按引用進行傳遞。

      =,&a, &b。除a和b按引用進行傳遞外,其他參數都按值進行傳遞。

      &, a, b。除a和b按值進行傳遞外,其他參數都按引用進行傳遞。

      ② 操作符重載函數參數;

      標識重載的()操作符的參數,沒有參數時,這部分可以省略。參數可以通過按值(如:(a,b))和按引用(如:(&a,&b))兩種方式進行傳遞。

      ③ 可修改標示符;

      mutable聲明,這部分可以省略。按值傳遞函數對象參數時,加上mutable修飾符后,可以修改按值傳遞進來的拷貝(注意是能修改拷貝,而不是值本身)。

      QPushButton * myBtn = new QPushButton (this);

      QPushButton * myBtn2 = new QPushButton (this);

      myBtn2->move(100,100);

      int m = 10;

      connect(myBtn,&QPushButton::clicked,this,[m] ()mutable { m = 100 + 10; qDebug() <

      connect(myBtn2,&QPushButton::clicked,this,[=] () { qDebug() << m; });

      qDebug() << m;

      ④ 函數返回值;

      ->返回值類型,標識函數返回值的類型,當返回值為void,或者函數體中只有一處return的地方(此時編譯器可以自動推斷出返回值類型)時,這部分可以省略。

      ⑤ 是函數體;

      {},標識函數的實現,這部分不能省略,但函數體可以為空。

      Qt

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:excel中將0變為短橫線的方法
      下一篇:在線文檔處理系統:提升工作效率的利器
      相關文章
      亚洲色欲或者高潮影院| 久久国产亚洲电影天堂| 亚洲精品美女在线观看| 亚洲av鲁丝一区二区三区| 亚洲av最新在线网址| 亚洲国产精品无码专区| 精品亚洲一区二区| 亚洲AV日韩AV永久无码下载| 亚洲精品国产精品乱码不卡√| 久久精品国产亚洲一区二区| 亚洲午夜国产精品无码老牛影视| 中文字幕亚洲电影| 亚洲国产日韩在线视频| 亚洲s色大片在线观看| 亚洲国产精品人久久| 亚洲色图国产精品| 亚洲综合男人的天堂色婷婷| 亚洲综合综合在线| 99热亚洲色精品国产88| 亚洲va久久久久| 色窝窝亚洲av网| 亚洲欧洲精品成人久久奇米网 | 亚洲人成亚洲人成在线观看| 精品国产综合成人亚洲区| 亚洲国产综合专区电影在线| 亚洲网站在线播放| 亚洲天堂2016| 亚洲av无码一区二区三区人妖 | 国产综合激情在线亚洲第一页 | 亚洲区视频在线观看| 在线亚洲高清揄拍自拍一品区| 亚洲日本VA午夜在线影院| 爱情岛论坛亚洲品质自拍视频网站 | 亚洲av日韩av永久无码电影| 亚洲成a人无码av波多野按摩| 亚洲熟伦熟女新五十路熟妇| 日本红怡院亚洲红怡院最新| 91亚洲国产成人精品下载| tom影院亚洲国产一区二区| 亚洲乱色伦图片区小说| 亚洲精品成a人在线观看|