QT进行两个窗口切换,理解信号与槽机制
主窗口和子窗口进行切换
子窗口头文件
#ifndef SUBWIDGET_H
#define SUBWIDGET_H
#include <QWidget>
#include <QString>
#include <QPushButton>
class subwidget : public QWidget
{
Q_OBJECT
public:
explicit subwidget(QWidget *parent = nullptr);
// 发送信号函数,用于子窗口返回主窗口
void sendSlot ();
// 在子窗口定义一个按钮 B
QPushButton B;
signals:
void mysignal ();
void mysignal (int a, QString str);
};
#endif // SUBWIDGET_H
主窗口头文件
#ifndef MAINWIDGET_H
#define MAINWIDGET_H
#include <QWidget>
#include "subwidget.h"
// 包含窗口的头文件
#include <QPushButton>
class MainWidget : public QWidget
{
Q_OBJECT
public:
MainWidget(QWidget *parent = nullptr);
~MainWidget();
public slots:
void changeSubWidgets ();
void changMainWidget ();
void dubge_data (int a, QString str);
private:
// 在主窗口定义按钮A1
QPushButton A1;
// 定义一个子窗口
subwidget subw;
};
#endif // MAINWIDGET_H
子窗口函数实现
#include "subwidget.h"
#include <QString>
subwidget::subwidget(QWidget *parent) : QWidget(parent)
{
this->setWindowTitle("子窗口");
this->resize(500, 500);
B.setParent(this);
B.setText("切换至主窗口");
B.move(100, 100);
connect (&B, &QPushButton::released, this, &subwidget::sendSlot);
}
void subwidget::sendSlot ()
{
emit mysignal ();
emit mysignal(250, "我是子窗口");
}
主窗口函数实现
#include "mainwidget.h"
#include <QDebug>
MainWidget::MainWidget(QWidget *parent)
: QWidget(parent)
{
// 设置主窗口的大小
this->resize(600, 600);
// 设置主窗口的标题
this->setWindowTitle("主窗口");
A1.setParent(this);
// 设置按钮标题
A1.setText("切换至子窗口");
A1.move(100, 100);
// 切换到子窗口
connect (&A1, &QPushButton::released, this, &MainWidget::changeSubWidgets);
// 切换到主窗口
// void (subwidget::*p1)() = &subwidget::mysignal;
// connect (&subw, p1, this, &MainWidget::changMainWidget);
//
//void (subwidget::*p2)(int, QString) = &subwidget::mysignal;
//connect (&subw, p2, this, &MainWidget::dubge_data);
// 信号槽的调用方式2
connect (&subw, SIGNAL(mysignal()), this, SLOT(changMainWidget ()));
connect (&subw, SIGNAL(mysignal(int, QString)), this, SLOT(dubge_data()));
// 但是这样的方式不太好,是QT4的语法,比较容易出错,是因为这样做如果将信号名写错,编译
// 阶段不会报错,只有运行阶段才能进行报错
}
MainWidget::~MainWidget()
{
}
void MainWidget::changeSubWidgets()
{
// 让子窗口出来
subw.show();
// 让主窗口退出
this->hide();
}
void MainWidget::changMainWidget ()
{
// 让主窗口出来
this->show();
// 让子窗口退出
subw.hide();
}
void MainWidget::dubge_data (int a, QString str)
{
// 打印
qDebug () << a << endl << str << endl;
}
主函数:
#include "mainwidget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWidget w;
w.show();
return a.exec();
}
总结:
(1)两个窗口进行切换,主窗口包含子窗口。
(2)主窗口上边有一个切换至子窗口的按钮,直接在主窗口写信号与槽函数就可以实现主窗口切换到子窗口了。
(3)子窗口要想切换回主窗口,直接写信号与槽函数是不行的,因为主窗口包含子窗口,但是子窗口没有包含主窗口。因此,直接写connect函数行不通,因此要用到信号函数
因此,在子窗口写信号函数 signals:
void mysignal ();
void mysignal (int a, QString str);
并且写一个发送信号函数:
void sendSlot ();
在子窗口函数实现模块将 sendSlot(); 函数写出来
sendSlot()
{
emit mysignal ();
emit mysignal(250, “我是子窗口”); // 这里写这个的目的是为了后边讨论信号函数重载
}
该怎么用?
(1)想要让子窗口切换会主窗口,肯定是将切换至主窗口的按钮点击一下,才会切换至主窗口。
因此,要在子窗口中写一个connect()信号与槽函数
所以
connect (&B, &QPushButton::released, this, &subwidget::sendSlot);
这个函数,就表示,B按钮发信号,子窗口接这个信号,完了调用sendSlot这个函数
(2)调用sendSlot函数之后,就产生一个信号,而这个信号让主窗口来接,在主窗口写一个connect信号与槽函数来接受这个信号,再进行窗口切换
(3)在主窗口当中:
connect (&subw, &subwidget::mysignal, this, &MainWidget::changeSubWidgets);
意思是子窗口发送mysignal信号,主窗口来接,调用changeSubWiagets函数,进行窗口切换
(4)总结:
子窗口不能直接写一个connect信号与槽函数,因为子窗口中没有包含主窗口,而是被包含,因此,需要借助信号来实现信号传递到主函数,然后进行窗口的切换。
信号与槽
// 切换到主窗口
void (subwidget::*p1)() = &subwidget::mysignal;
connect (&subw, p1, this, &MainWidget::changMainWidget);
// 打印输出
void (subwidget::*p2)(int, QString) = &subwidget::mysignal;
connect (&subw, p2, this, &MainWidget::dubge_data);
// 信号槽的调用方式2
connect (&subw, SIGNAL(mysignal()), this, SLOT(changMainWidget ()));
connect (&subw, SIGNAL(mysignal(int, QString)), this, SLOT(dubge_data()));
// 但是这样的方式不太好,是QT4的语法,比较容易出错,是因为这样做如果将信号名写错,编译
// 阶段不会报错,只有运行阶段才能进行报错
上边两种方式,是利用函数指针来解决信号函数二义性的问题
下边两行是采用QT4的语法来进行解决
但是一般采用上边的方式比下边这两行的要好。因为下边这两行如果信号函数名写错了,在编译阶段不会被发现,这样是不太好的。