• 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",可能会输出u6211u662Fu5B32u3291.二进制编码

    解决方法:

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

    }

  • 相关阅读:
    DateGridView 分页显示
    DataGridView 隔行显示不同的颜色
    DataGridview 绘制行序号
    DataGrridView 当前行显示不同颜色
    右键删除行
    【bzoj2763】[JLOI2011]飞行路线 分层图最短路
    【bzoj1143】[CTSC2008]祭祀river Floyd+网络流最小割
    【bzoj1029】[JSOI2007]建筑抢修 贪心+堆
    【bzoj1054】[HAOI2008]移动玩具 Bfs
    【bzoj1911】[Apio2010]特别行动队 斜率优化dp
  • 原文地址:https://www.cnblogs.com/gd-luojialin/p/9215696.html
Copyright © 2020-2023  润新知