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();

}

 

posted @ 2018-06-22 22:28  gd_沐辰  阅读(6980)  评论(0编辑  收藏  举报