zoukankan      html  css  js  c++  java
  • Qt5教程: (3) 自定义信号与槽

    1. 自定义槽

    • 槽可以是任何成员函数、普通全局函数、静态函数
    • 槽函数和信号的参数和返回值要一致
    • 由于信号是没有返回值的, 槽函数也一定没有返回值
      首先在mainwidget.h中添加槽函数:
    public slots:
        void mySlot();
    

    之后在mainwidget.cpp文件中定义槽函数:

    void MainWidget::mySlot()
    {
        b2->setText("^_^");
    }
    

    现在, 我们希望当Button2按下时, Button2显示的文本变成笑脸, 就需要将Button2的信号和我们自定义的槽函数连接:

    connect(b2, &QPushButton::clicked, this, &MainWidget::mySlot);
    

    保存后运行, 点击Button2就会变成笑脸了:

    附录

    mainwidget.h

    #ifndef MAINWIDGET_H
    #define MAINWIDGET_H
    
    #include <QWidget>
    #include <QPushButton>
    
    class MainWidget : public QWidget
    {
        Q_OBJECT
    
    public:
        MainWidget(QWidget *parent = 0);
        ~MainWidget();
    
    public slots:
        void mySlot();
    
    private:
        QPushButton b1;
        QPushButton *b2;
    };
    
    #endif // MAINWIDGET_H
    

    mainwidget.cpp

    #include "mainwidget.h"
    
    MainWidget::MainWidget(QWidget *parent)
        : QWidget(parent)
    {
        b1.setParent(this);
        b1.setText("Close");
        b1.move(50, 50);
    
        b2 = new QPushButton(this);
        b2->setText("Button2");
        b2->move(150, 50);
    
        connect(&b1, &QPushButton::clicked, this, &MainWidget::close);
    
        connect(b2, &QPushButton::clicked, this, &MainWidget::mySlot);
    
    }
    
    void MainWidget::mySlot()
    {
        b2->setText("^_^");
    }
    
    MainWidget::~MainWidget()
    {
    
    }
    

    2. 自定义信号

    目标: 实现两个独立窗口之间的切换, 点击"Next" 跳到下一个窗口, 点击"Back" 返回到上一个窗口.

    • 信号没有返回值, 但可以有参数
    • 信号只有函数声明, 无需定义
    • 使用emit 发送信号
      首先修改当前窗口标题为"Window1", 并设置窗口大小:
        this->setWindowTitle("Window1");  // this->可以省略
        this->resize(300, 200);  // 长300, 宽200
    

    之后修改Button2的文本"Button2"为"Next"
    新建一个窗口
    右键工程目录"SignalAndSlot" --> Add New:

    选择 C++ --> C++ Class --> Choose:

    输入Class name为SubWidget, Base class为QWidget, 点击Next, 点击Finish:

    之后一个新的窗口类就新建好了:

    修改新窗口的标题:
    在subwidget.cpp中构造函数下, 设置窗口的标题为"Window2", 大小和Windows1一样:

        this->setWindowTitle("Windows2");
        this->resize(300, 200);
    

    在新窗口中加入按键:
    首先, 在subwidget.h中添加头文件, 然后声明按钮 b:

    private:
        QPushButton b;
    

    在subwidget.cpp中, 对按钮进行编辑:

        b.setParent(this);
        b.setText("Back");
        b.move(150, 50);
    

    实例化SubWidget:
    但是, 我们仅仅是写了一个新窗口的类, 还没有实例化, 所以我们在mainwidget.h中先包含subwidget的头文件, 然后实例化一个副窗口subWin对象:

        SubWidget subWin;
    

    建立信号与槽的连接:
    接下来, 我们来实现点击"Next"显示Windows2功能, 其实就是b2点击这个信号, 触发副窗口的show(), 并隐藏主窗口.
    将mainwidget.h和mainwidget.cpp中所有的mySlot改为nextSlot. (共三处)
    我们修改mainwidget.cpp中nextSlot()的定义:

    void MainWidget::nextSlot()
    {
        //  删除 b2->setText("^_^");
        subWin.show();
        this->hide();
    }
    

    connect(b2, &QPushButton::clicked, this, &MainWidget::nextSlot);不变. 保存并运行, 就可以实现切换到Window2窗口了. 但是还没有返回主窗口功能.
    信号的创建和发送:
    要实现Back功能, 就需要在"Back"按钮按下后, 副窗口发送一个信号, 然后主窗口收到这个信号后, 显示自己, 隐藏副窗口, 逻辑如下:
    Back按下的信号 ----> 副窗口发送信号
    副窗口的信号 ----> 主窗口show, 副窗口hide
    下面看代码怎么写:
    在subwidget.h中声明一个自定义的信号, 和用于发送该信号的槽函数:

    signals:
        void backSignal();
    
    public slots:
        void sendSignal();
    

    由于信号只需声明, 无需定义, 所以只要在subwidget.cpp定义槽函数来发送信号:

    void SubWidget::sendSignal()
    {
        emit backSignal();
    }
    

    之后在Back按钮按下后, 通过这个槽函数发送返回信号:

    connect(&b, &QPushButton::clicked, this, &SubWidget::sendSignal);
    

    在mainwidget中需要再定义一个槽函数来处理back信号:
    在mainwidget.h中声明槽函数

        void backSlot();
    

    之后在mainwidget.cpp中定义:

    void MainWidget::backSlot()
    {
        this->show();
        subWin.hide();
    }
    

    之后connect信号与槽, 收到副窗口发送的信号后返回主窗口:

        connect(&subWin, &SubWidget::backSignal, this, &MainWidget::backSlot);
    

    保存后运行, 现在可以在两个界面中切换了.

    附录

    mainwidget.h

    #ifndef MAINWIDGET_H
    #define MAINWIDGET_H
    
    #include <QWidget>
    #include <QPushButton>
    #include "subwidget.h"
    
    class MainWidget : public QWidget
    {
        Q_OBJECT
    
    public:
        MainWidget(QWidget *parent = 0);
        ~MainWidget();
    
    public slots:
        void nextSlot();
        void backSlot();
    
    private:
        QPushButton b1;
        QPushButton *b2;
    
        SubWidget subWin;
    };
    
    #endif // MAINWIDGET_H
    

    mainwidget.cpp

    #include "mainwidget.h"
    
    MainWidget::MainWidget(QWidget *parent)
        : QWidget(parent)
    {
        this->setWindowTitle("Window1");
        this->resize(300, 200);
        b1.setParent(this);
        b1.setText("Close");
        b1.move(50, 50);
    
        b2 = new QPushButton(this);
        b2->setText("Next");
        b2->move(150, 50);
    
        connect(&b1, &QPushButton::clicked, this, &MainWidget::close);
        connect(b2, &QPushButton::clicked, this, &MainWidget::nextSlot);
        connect(&subWin, &SubWidget::backSignal, this, &MainWidget::backSlot);
    
    }
    
    void MainWidget::nextSlot()
    {
        subWin.show();
        this->hide();
    }
    
    void MainWidget::backSlot()
    {
        subWin.hide();
        this->show();
    }
    
    MainWidget::~MainWidget()
    {
    
    }
    
    

    subwidget.h

    #ifndef SUBWIDGET_H
    #define SUBWIDGET_H
    
    #include <QWidget>
    #include <QPushButton>
    
    class SubWidget : public QWidget
    {
        Q_OBJECT
    public:
        explicit SubWidget(QWidget *parent = nullptr);
    
    signals:
        void backSignal();
    
    public slots:
        void sendSignal();
    
    private:
        QPushButton b;
    };
    
    #endif // SUBWIDGET_H
    
    

    subwidget.cpp

    #include "subwidget.h"
    
    SubWidget::SubWidget(QWidget *parent) : QWidget(parent)
    {
        this->setWindowTitle("Windows2");
        this->resize(300, 200);
    
        b.setParent(this);
        b.setText("Back");
        b.move(150, 50);
    
        connect(&b, &QPushButton::clicked, this, &SubWidget::sendSignal);
    }
    
    void SubWidget::sendSignal()
    {
        emit backSignal();
    }
    
    

    此文原创禁止转载,转载文章请联系博主并注明来源和出处,谢谢!
    作者: Raina_RLN https://www.cnblogs.com/raina/

  • 相关阅读:
    C++ 小心你的析构函数不会执行
    sqlserver同步服务报错和链接服务器总结
    第37周星期5小结
    代码审核学到的两个delphi内存泄漏问题
    第36周星期四小结如何测试sql服务是否安装并正常运行
    第37周星期日
    第37周星期六几篇文摘
    第36周星期五小结
    第37周星期一小结
    2012年第37周星期三小结
  • 原文地址:https://www.cnblogs.com/raina/p/11312097.html
Copyright © 2011-2022 走看看