Qt信号与槽之自定义信号

Qt信号与槽之自定义信号

本节在Qt信号与槽之标准信号的基础上继续实验,目的在于掌握自定义信号的使用

实验任务如下:

  • 创建一个子窗口subWin
  • 在窗口w和subWin中分别生成一个按钮,使得按下按钮时能实现窗口切换(一个显示时另一个不显示)

实验步骤如下:

  1. 新建子窗口SubWidget类

    • 右击SignalAndSlot项目 --> C++ --> C++ Class --> Choose
    • Base class: QWidget --> Class name: SubWidget --> 下一步 --> 完成
  2. 在mainwidget.h中为MainWidget类添加私有成员b3和subWin

    #include "subwidget.h"
    //...(略)
    private:
        QPushButton b1;
        QPushButton b2;
        QPushButton b3;  	//窗口切换按钮
        SubWidget subWin;	//子窗口
    
  3. 实现从主窗口切换到子窗口的功能

    • 在mainwidget.cpp中MainWidget类的构造函数里加入以下代码
        //按钮b3
        b3.setParent(this);
        b3.setText("切换到子窗口");
        b3.move(100, 0);
    
        connect(&b3, &QPushButton::pressed, this, &MainWidget::showSub);  //显示子窗口
    
    • 在mainwidget.h中声明showSub
    public:
    	void showSub();
    
    • 在mainwidget.cpp中定义showSub
    void MainWidget::showSub()
    {
        hide();
        subWin.show();
    }
    
  4. 实现从子窗口切换到主窗口的功能(涉及自定义信号)

    • 在subwidget.h中为SubWidget类添加私有成员b、mySignal以及sendSignal
    #include <QPushButton>
    //...(略)
    
    public:
        void sendSignal();
    
    private:
        QPushButton b;
    
    signals:
        void mySignal();
    
    
    • 在subwidget.cpp中设置窗口和按钮等,并实现sendSignal函数
    #include "subwidget.h"
    
    SubWidget::SubWidget(QWidget *parent) : QWidget(parent)
    {
        //子窗口
        resize(400, 200);
        setWindowTitle("小弟");
        
        //按钮b
        b.setParent(this);
        b.setText("切换到主窗口");
        
        connect(&b, &QPushButton::pressed, this, &SubWidget::sendSignal);
    }
    
    void SubWidget::sendSignal()
    {
        emit mySignal();
    }
    
    • 在mainwidget.cpp中MainWidget类的构造函数里加入以下代码
    	connect(&subWin, &SubWidget::mySignal, this, &MainWidget::showMain);  //显示主窗口
    
    • 在mainwidget.h中声明showMain函数(略),接着在mainwidget.cpp中实现showMain函数
    void MainWidget::showMain()
    {
        show();
        subWin.hide();
    }
    
  5. 编译运行,测试实验效果

总结:

  • 不能在构造函数里生成按钮,因为函数执行完时按钮作为局部变量会被回收
  • 如果想将一个窗口中构件的信号传递给另外一个(独立的)窗口,可以通过自定义信号并实现信号发送函数的方式来实现

完整代码附录:

  • 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();
        void changeText();
        void showSub();
        void showMain();
    
    private:
        QPushButton b1;
        QPushButton b2;
        QPushButton b3;
        SubWidget subWin;
    };
    
    #endif // MAINWIDGET_H
    
  • subwidget.h

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

    #include "mainwidget.h"
    
    MainWidget::MainWidget(QWidget *parent)
        : QWidget(parent)
    {
        //窗口
        resize(600, 400);
        setWindowTitle("老大");
    
        //按钮b1
        b1.setParent(this);
        b1.setText("abc");
    
        //按钮b2
        b2.setParent(this);
        b2.setText("close");
        b2.move(200, 200);
    
        //按钮b3
        b3.setParent(this);
        b3.setText("切换到子窗口");
        b3.move(100, 0);
    
        //信号与槽:Qt对象之间通信的接口
        //信号与槽如同短信和手机:一个信号可以被多个槽接收
        //信号发出者、处理的信号、信号接收者、槽函数(信号处理函数)
        connect(&b1, &QPushButton::pressed, this, &MainWidget::changeText);
        connect(&b2, &QPushButton::released, this, &MainWidget::close);
    
        //窗口切换
        connect(&b3, &QPushButton::pressed, this, &MainWidget::showSub);  //显示子窗口
        connect(&subWin, &SubWidget::mySignal, this, &MainWidget::showMain);  //显示主窗口
    }
    
    MainWidget::~MainWidget()
    {
    
    }
    
    //可以像定义普通函数一样自定义槽函数
    //在Qt5中,槽可以为任意的成员函数,普通全局函数,静态函数
    //槽函数需要与信号一致(参数,返回值),因为信号都没有返回值,所以槽函数一定没有返回值
    void MainWidget::changeText()
    {
        b1.setText("123");
    }
    
    void MainWidget::showSub()
    {
        hide();
        subWin.show();
    }
    
    void MainWidget::showMain()
    {
        show();
        subWin.hide();
    }
    
  • subwidget.cpp

    #include "subwidget.h"
    
    SubWidget::SubWidget(QWidget *parent) : QWidget(parent)
    {
        //子窗口
        resize(400, 200);
        setWindowTitle("小弟");
    
        //按钮b
        b.setParent(this);
        b.setText("切换到主窗口");
    
        connect(&b, &QPushButton::pressed, this, &SubWidget::sendSignal);
    }
    
    void SubWidget::sendSignal()
    {
        emit mySignal();
    }
    
  • main.cpp

    #include "mainwidget.h"
    #include <QApplication>
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        MainWidget w;  //执行MainWidget的构造函数
        w.show();
    
        return a.exec();
    }
    
posted @ 2021-01-15 08:10  夏恒  阅读(277)  评论(0编辑  收藏  举报