中國(guó)數(shù)據(jù)域名注冊(cè)重慶seo
目錄
概念
代碼
mainwindow.h
me.h
xiaohuang.h
main.cc
mainwindow.cc
me.cc
xianghuang.cc
mainwindow.ui
自定義信號(hào)的要求和注意事項(xiàng):
自定義槽的要求和注意事項(xiàng):
概念
信號(hào)槽是 Qt 框架引以為豪的機(jī)制之一。所謂信號(hào)槽,實(shí)際就是觀察者模式(發(fā)布-訂閱模式)。當(dāng)某個(gè)
事件
發(fā)生之后,比如,按鈕檢測(cè)到自己被點(diǎn)擊了一下,它就會(huì)發(fā)出一個(gè)信號(hào)(signal)。這種發(fā)出是沒(méi)有目的的,類似廣播。如果有對(duì)象對(duì)這個(gè)信號(hào)感興趣,它就會(huì)使用連接(connect)函數(shù),意思是,將想要處理的信號(hào)和自己的一個(gè)函數(shù)(稱為槽(slot))綁定來(lái)處理這個(gè)信號(hào)。也就是說(shuō),當(dāng)信號(hào)發(fā)出時(shí),被連接的槽函數(shù)會(huì)自動(dòng)被回調(diào)。這就類似觀察者模式:當(dāng)發(fā)生了感興趣的事件,某一個(gè)操作就會(huì)被自動(dòng)觸發(fā)。信號(hào)?的本質(zhì)就是事件
信號(hào)的呈現(xiàn)形式就是函數(shù), 也就是說(shuō)某個(gè)事件產(chǎn)生了, Qt框架就會(huì)調(diào)用某個(gè)對(duì)應(yīng)的信號(hào)函數(shù), 通知使用者。
槽函數(shù)是一類特殊的功能的函數(shù)
,在編碼過(guò)程中也可以作為類的普通成員函數(shù)來(lái)使用
。之所以稱之為槽函數(shù)是因?yàn)樗鼈冞€有一個(gè)職責(zé)就是對(duì)Qt框架中產(chǎn)生的信號(hào)進(jìn)行處理。在Qt中信號(hào)和槽函數(shù)都是獨(dú)立的個(gè)體,本身沒(méi)有任何聯(lián)系,但是由于某種特性需求我們可以將二者連接到一起,在Qt中我們需要使用
QOjbect類
中的connect
函數(shù)進(jìn)二者的關(guān)聯(lián)。
代碼
mainwindow.h
#ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow> #include "me.h" #include "xiaohuang.h"QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACEclass MainWindow : public QMainWindow {Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();//添加HungryBtn的槽函數(shù)void HungrySlot();private:Ui::MainWindow *ui;Me* _me;Xiaohuang* _xh; }; #endif // MAINWINDOW_H
me.h
#ifndef ME_H #define ME_H#include <QObject>class Me : public QObject {Q_OBJECT public:explicit Me(QObject *parent = nullptr);public slots:void eat();void eat(QString msg);};#endif // ME_H
xiaohuang.h
#ifndef XIAOHUANG_H #define XIAOHUANG_H#include <QObject>class Xiaohuang : public QObject {Q_OBJECT public:explicit Xiaohuang(QObject *parent = nullptr);signals:void hungry();void hungry(QString msg); };#endif // XIAOHUANG_H
main.cc
#include "mainwindow.h"#include <QApplication>int main(int argc, char *argv[]) {QApplication a(argc, argv);MainWindow w;w.show();return a.exec(); }
mainwindow.cc
#include "mainwindow.h" #include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow) {ui->setupUi(this);//方法一:標(biāo)準(zhǔn)信號(hào)和槽函數(shù)connect(ui->closeBtn,&QPushButton::clicked,this,&MainWindow::close);//方法二:自定義信號(hào)和槽函數(shù)_me = new Me;_xh = new Xiaohuang;//因?yàn)樽远x的信號(hào)不能讓qt框架去發(fā)送,所以我們用qt框架有的信號(hào)關(guān)聯(lián)我們的自定義信號(hào)//間接去讓他發(fā)送我們的自定義信號(hào)//a 這個(gè)是信號(hào)連接槽函數(shù)去間接發(fā)送信號(hào)//connect(ui->HungryBtn,&QPushButton::clicked,this,&MainWindow::HungrySlot);//b 現(xiàn)在我們信號(hào)連接信號(hào)//connect(ui->HungryBtn,&QPushButton::clicked,_xh,&Xiaohuang::hungry);//connect(_xh,&Xiaohuang::hungry,_me,&Me::eat);//但是對(duì)于帶參的,Qt5這么寫(xiě)就有問(wèn)題,因?yàn)橹剌d了,所以編譯器就不知道選帶參還是不帶的,所以有語(yǔ)法錯(cuò)誤//我們就可以在外部定義一個(gè)函數(shù)指針來(lái)說(shuō)明是帶參的還是不帶參的//void (Xiaohuang::* Xh1)() = &Xiaohuang::hungry;void (Xiaohuang::* Xh2)(QString) = &Xiaohuang::hungry;void (Me::* myp)(QString) = &Me::eat;//對(duì)于有傳參的寫(xiě)法connect(_xh,Xh2,_me,myp);connect(_xh,Xh2,_me,myp);//我們上面是Qt5的信號(hào)和槽處理方式,現(xiàn)在我們來(lái)看Qt4的connect(_xh,SIGNAL(hungry()),_me,SLOT(eat()));//對(duì)于有傳參的寫(xiě)法connect(_xh,SIGNAL(hungry(QString)),_me,SLOT(eat(QString)));connect(ui->HungryBtn,&QPushButton::clicked,this,&MainWindow::HungrySlot);//推薦使用Qt5,因?yàn)镼t4是宏替換,沒(méi)有安全檢查 }MainWindow::~MainWindow() {delete ui; }void MainWindow::HungrySlot() {//按下按鈕,發(fā)送自定義信號(hào)emit _xh->hungry();emit _xh->hungry("海鮮"); }
me.cc
#include "me.h" #include <QDebug>Me::Me(QObject *parent) : QObject(parent) {}void Me::eat() {qDebug()<<"我?guī)闳コ燥?#34;; }void Me::eat(QString msg) {qDebug()<<"我?guī)闳コ?"<<msg; }
xianghuang.cc
#include "xiaohuang.h"Xiaohuang::Xiaohuang(QObject *parent) : QObject(parent) {}
mainwindow.ui
自定義信號(hào)的要求和注意事項(xiàng):
信號(hào)是類的成員函數(shù)
返回值必須是 void 類型
信號(hào)的名字可以根據(jù)實(shí)際情況進(jìn)行指定
參數(shù)可以隨意指定,?信號(hào)也支持重載
信號(hào)需要使用 signals 關(guān)鍵字進(jìn)行聲明, 使用方法類似于public等關(guān)鍵字
信號(hào)函數(shù)只需要聲明, 不需要定義(沒(méi)有函數(shù)體實(shí)現(xiàn))
在程序中發(fā)射自定義信號(hào): 發(fā)送信號(hào)的本質(zhì)就是調(diào)用信號(hào)函數(shù)
習(xí)慣性在信號(hào)函數(shù)前加關(guān)鍵字: emit, 但是可以省略不寫(xiě)
emit只是顯示的聲明一下信號(hào)要被發(fā)射了, 沒(méi)有特殊含義
底層 emit == #define emit
// 舉例: 信號(hào)重載 // Qt中的類想要使用信號(hào)槽機(jī)制必須要從QObject類派生(直接或間接派生都可以) class Test : public QObject {Q_OBJECT signals:void testsignal();// 參數(shù)的作用是數(shù)據(jù)傳遞, 誰(shuí)調(diào)用信號(hào)函數(shù)誰(shuí)就指定實(shí)參// 實(shí)參最終會(huì)被傳遞給槽函數(shù)void testsignal(int a); };
自定義槽的要求和注意事項(xiàng):
返回值必須是 void 類型
槽也是函數(shù), 因此也支持重載
槽函數(shù)需要指定多少個(gè)參數(shù), 需要看連接的信號(hào)的參數(shù)個(gè)數(shù)
槽函數(shù)的參數(shù)是用來(lái)接收信號(hào)傳遞的數(shù)據(jù)的,?信號(hào)傳遞的數(shù)據(jù)就是信號(hào)的參數(shù)
- 舉例:
- 信號(hào)函數(shù): void testsig(int a, double b);
- 槽函數(shù): void testslot(int a, double b);
- 總結(jié):
- 槽函數(shù)的參數(shù)應(yīng)該和對(duì)應(yīng)的信號(hào)的參數(shù)個(gè)數(shù), 從左到右類型依次對(duì)應(yīng)
- 信號(hào)的參數(shù)可以大于等于槽函數(shù)的參數(shù)個(gè)數(shù) ==?信號(hào)傳遞的數(shù)據(jù)被忽略了
- 信號(hào)函數(shù): void testsig(int a, double b);
- 槽函數(shù): void testslot(int a);
Qt中槽函數(shù)的類型是多樣的
Qt中的槽函數(shù)可以是
類的成員函數(shù)
、全局函數(shù)
、靜態(tài)函數(shù)
、Lambda表達(dá)式
(匿名函數(shù))
槽函數(shù)可以使用關(guān)鍵字進(jìn)行聲明: slots (Qt5中slots可以省略不寫(xiě))
- public slots:
- private slots: –> 這樣的槽函數(shù)不能在類外部被調(diào)用
- protected slots: –> 這樣的槽函數(shù)不能在類外部被調(diào)用
// 槽函數(shù)書(shū)寫(xiě)格式舉例 // 類中的這三個(gè)函數(shù)都可以作為槽函數(shù)來(lái)使用 class Test : public QObject {public:void testSlot();static void testFunc();public slots:void testSlot(int id); };