4自定義信號和槽函數


自定義信號和槽

      信號和槽的本質都是函數。

區別:

信號必須由signal關鍵字來聲明

信號可以重載

信號沒有返回值,但可以有參數。由於信號都是沒有返回值,所以,槽函數一定沒有返回值

     信號就是函數的聲明,只需聲明,無需定義。槽既要函數聲明也要完成定義。

     使用方式:emit MySignal();

 

例子說明:本例創建兩個獨立的窗口,分別在窗口中放置一個按鈕,由此來進行兩個窗口的切換。如:“切換到子窗口”,即子窗口顯示,主窗口隱藏。反之亦然。

按照之前的方式創建程序,另外在項目中“添加新文件”->“C++ class”,名為csubwnd。即創建兩個類,作為主窗口(widget)和子窗口(csubwnd)。

思路:

      創建兩個類,主窗口類來處理窗口的切換,本來只顯示窗口,當收到子窗口發出的信號后,立即顯示子窗口並隱藏主窗口。而子窗口類只負責發出信號。

 

自定義信號

      一定要在Signal中聲明(頭文件中)。

signals:

void MySignal();

 

使用方式:

connect(&subPush,&QPushButton::released,this,&CSubWnd::MySlot);

 

void CSubWnd::MySlot()

{

    emit MySignal();

}

 

其中MySlot()是自定義槽函數(具體見上一節內容)。emit MySignal()代表發出信號。

解析:當按鈕subPush被釋放時,this(本窗口)立即調用槽函數(MySlot)發出信號(MySignal)。由此可以看到,信號只需聲明無需定義,槽函數既要聲明也要定義。

 

主窗口的信號處理:

void Widget::Base()

{

    //主窗口隱藏

    this->hide();

    //子窗口顯示

    subWnd.show();

}

 

void Widget::Sub()

{

    //主窗口顯示

    this->show();

    //子窗口隱藏

    subWnd.hide();

}

 

{

   //激活槽函數,切換到子窗口

    connect(&push,&QPushButton::released,this,&Widget::Base);

   

    //接受子窗口的信號,切換到主窗口

    connect(&subWnd,&CSubWnd::MySignal,this,&Widget::Sub);

}

其中,push代表“切換到子窗口”按鈕,subWnd代表“切換到主窗口”的按鈕,MySignal是子窗口發出的信號。Base和Sub是兩個用於切換窗口的槽函數。

 

帶參數的信號

      前面說過信號啊可以重載,下面重載一個帶參數的信號。

信號聲明:

signals:

    //自擬信號

    void MySignal();

void MySignal(int ,QString);

 

調用信號:

void CSubWnd::MySlot()

{

    //發出自擬信號

    emit MySignal();

    emit MySignal(2018,"I am learnning Qt,我學習QT");

}

槽函數定義:

void Widget::TextSignal(int nNum,QString strChar)

{

    qDebug()<<nNum<<strChar;

}

注意:信號和槽函數的參數必須一致,如信號void MySignal(int ,QString),即槽函數TextSignal也必須兩個參數,且為類型為int和Qstring。

 

補充:

qDebug()是輸出函數,類似於C++中的cout。qDebug()的頭文件是<QDebug>,但使用時要注意qDebug(),q是小寫,並且帶上括號。

 

信號與槽函數的使用:

//Qt5版本帶參數的信號

    void (CSubWnd::*NoSub)()=&CSubWnd::MySignal;

    connect(&subWnd,NoSub,this,&Widget::Sub);

 

    void (CSubWnd::*Sub)(int,QString)=&CSubWnd::MySignal;

    connect(&subWnd,Sub,this,&Widget::TextSignal);

 

問題:為什么要使用函數指針,而不是直接信號本身,如下:

connect(&subWnd, &CSubWnd::MySignal,this,&Widget::Sub);

connect(&subWnd, &CSubWnd::MySignal,this,&Widget:: TextSignal);

原因:

在前面的信號聲明。   void MySignal();void MySignal(int ,QString);使用的是重載,如果直接信號名,會產生二義性,編譯器無法獲取發出的信號是哪一個?帶參數還是不帶參數。

 

當然,也有一種簡便方式.

//Qt4版本,與Qt5使用函數指針效果等價

connect(&subWnd,SIGNAL(MySignal()),this,SLOT(Sub()));

connect(&subWnd,SIGNAL(MySignal(int,QString)),this,SLOT(TextSignal(int,QString)));

 

注意:如果使用Qt4版本。SINAL,SLOT都是宏。

  1. SINAL,SLOT將函數名字轉換成字符串,不進行錯誤檢查,如:SIGNAL(MySigl()),拼寫錯誤了,編譯器也會通過,但是會在執行的過程中才中斷報錯。
  2. 槽函數必須使用slots關鍵字來聲明,否則無法識別,會報出無法尋查該函數。

public slots:

           void Base();         //切換到子窗口

   void Sub();          //切換到主窗口

      void TextSignal(int ,QString);        //測試帶參數信號

 

補充:輸出編碼問題

  qDebug()<<nNum<<strChar;

當string=“我學習QT",可能會輸出\u6211\u662F\u5B32\u3291.二進制編碼

解決方法:

 qDebug()<<nNum<<strChar.toUtf8().data();

 

 

解析

strChar.toUtf8()->字節數組QbyteArray

…data()->QbyteArray->char*.

此時就可以輸出中文了。也可以是其他類型的編碼。可以在qt編譯器->工具->選項->文本編輯器.可以查看當前自己的編碼類型。

 

源代碼:

csubwnd.h

#ifndef CSUBWND_H

#define CSUBWND_H

 

#include <QWidget>

#include <QPushButton>

 

class CSubWnd : public QWidget

{

    Q_OBJECT

public:

    explicit CSubWnd(QWidget *parent = 0);

   

    //發出信號的槽函數

    void MySlot();

signals:

    //自擬信號

void MySignal();

void MySignal(int ,QString);

public slots:

 

private:

    //按鈕

    QPushButton subPush;

};

 

#endif // CSUBWND_H

 

 

 

widget.h

#ifndef WIDGET_H

#define WIDGET_H

 

#include <QWidget>

#include <QPushButton>

#include "csubwnd.h"

 

namespace Ui {

class Widget;

}

 

class Widget : public QWidget

{

    Q_OBJECT

 

public:

    explicit Widget(QWidget *parent = 0);

    ~Widget();

public slots:

   void Base();         //切換到子窗口

  

   void Sub();          //切換到主窗口

   void TextSignal(int ,QString);        //測試帶參數信號

private:

    Ui::Widget *ui;

    QPushButton push;

    //子窗口類

    CSubWnd subWnd;

};

 

#endif // WIDGET_H

 

 

 

csubwnd.cpp

#include "csubwnd.h"

 

CSubWnd::CSubWnd(QWidget *parent) :

    QWidget(parent)

{

    this->setWindowTitle("子窗口");

    subPush.setParent(this);

    subPush.setText("切換到主窗口");

    this->show();

   

    //點擊按鈕后,利用槽函數發出信號

    connect(&subPush,&QPushButton::released,this,&CSubWnd::MySlot);

 

    resize(400,300);

}

 

void CSubWnd::MySlot()

{

    //發出自擬信號

emit MySignal();

emit MySignal(2018,"I am learnning Qt,我學習QT");

}

 

 

 

main.cpp

#include "widget.h"

#include <QApplication>

 

int main(int argc, char *argv[])

{

    QApplication a(argc, argv);

    Widget w;

    w.show();

 

    return a.exec();

}

 

 

 

widget.cpp

#include "widget.h"

#include "ui_widget.h"

 

Widget::Widget(QWidget *parent) :

    QWidget(parent),

    ui(new Ui::Widget)

{

    ui->setupUi(this);

 

    this->setWindowTitle("主窗口");

    push.setText("切換到子窗口");

    push.setParent(this);

   

    //激活槽函數,切換到子窗口

    connect(&push,&QPushButton::released,this,&Widget::Base);

    //接受子窗口的信號,切換到主窗口

   // connect(&subWnd,&CSubWnd::MySignal,this,&Widget::Sub);

   

//Qt5版本帶參數的信號

    //void (CSubWnd::*NoSub)()=&CSubWnd::MySignal;

//connect(&subWnd,NoSub,this,&Widget::Sub);

 

    //void (CSubWnd::*Sub)(int,QString)=&CSubWnd::MySignal;

    //connect(&subWnd,Sub,this,&Widget::TextSignal);

 

    //Qt4版本,與Qt5使用函數指針效果等價

    connect(&subWnd,SIGNAL(MySignal()),this,SLOT(Sub())); connect(&subWnd,SIGNAL(MySignal(int,QString)),this,SLOT(TextSignal(int,QString)));

 

    //設置窗口大小

    resize(400,300);

}

 

Widget::~Widget()

{

    delete ui;

}

 

void Widget::Base()

{

    //主窗口隱藏

    this->hide();

    //子窗口顯示

    subWnd.show();

}

 

void Widget::Sub()

{

    //主窗口顯示

    this->show();

    //子窗口隱藏

    subWnd.hide();

}

 

void Widget::TextSignal(int nNum,QString strChar)

{

    qDebug()<<nNum<<strChar.toUtf8().data();

}

 


免責聲明!

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



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