Qt信号与槽之自定义信号
Qt信号与槽之自定义信号
本节在Qt信号与槽之标准信号的基础上继续实验,目的在于掌握自定义信号的使用
实验任务如下:
- 创建一个子窗口subWin
- 在窗口w和subWin中分别生成一个按钮,使得按下按钮时能实现窗口切换(一个显示时另一个不显示)
实验步骤如下:
-
新建子窗口SubWidget类
- 右击SignalAndSlot项目 --> C++ --> C++ Class --> Choose
- Base class: QWidget --> Class name: SubWidget --> 下一步 --> 完成
-
在mainwidget.h中为MainWidget类添加私有成员b3和subWin
#include "subwidget.h" //...(略) private: QPushButton b1; QPushButton b2; QPushButton b3; //窗口切换按钮 SubWidget subWin; //子窗口
-
实现从主窗口切换到子窗口的功能
- 在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(); }
-
实现从子窗口切换到主窗口的功能(涉及自定义信号)
- 在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(); }
-
编译运行,测试实验效果
总结:
- 不能在构造函数里生成按钮,因为函数执行完时按钮作为局部变量会被回收
- 如果想将一个窗口中构件的信号传递给另外一个(独立的)窗口,可以通过自定义信号并实现信号发送函数的方式来实现
完整代码附录:
-
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(); }