QT作业1:实现两个窗口的切换

本文介绍了使用Qt实现两个窗口切换的三种方法。首先分析了需求,即在点击按钮时实现窗口的隐藏与显示。第一种方法是通过重载构造函数建立窗口间的连接;第二种方法是利用自定义信号和槽;第三种方法是创建一个新的类来管理窗口并使用自定义信号。每种方法都涉及到信号和槽机制以及对象间的通信。
摘要由CSDN通过智能技术生成

1 需求

在这里插入图片描述
设计两个窗口,每个窗口中都包含一个按钮,最开始的时候只显示窗口1,当按下窗口1中的按钮时,窗口1隐藏(hide),同时窗口2显示(show),当按下窗口2中的按钮时,窗口2隐藏,窗口1显示。

2 分析

这个案例最关键的是,如何让两个窗口建立连接(connect),最开始学QT的时候,我们都是在Widget的构造函数中调用connect函数,但这里不能直接这样做,因为创建的时候,你拿不到另一个Widget对象,如果通过构造函数的参数传进来,则传进来的那个Widget该如何构建?解决这个问题可以使用两种方法:
1 重载构造函数,例如w1通过无参构造函数创建,w2通过有参,w2在创建的时候将w1传进去,然后在有参构造函数中建立联系(connect)
2 新建一个类A,这个类A必须直接或间接继承QObject,这样才能获得connect函数(因为connect是QObject的成员函数),然后将w1和w2都作为A的成员变量,并在A的构造函数中实现两个窗口的连接

需要注意的一点是,信号的发送者是QPushButton指针,而不是窗口对象,并且,为了建立两个窗口的联系,最好将QPushButton指针作为Widget类的成员变量,这样通过窗口就能拿到信号发送者,详见下面的代码。

还有第三种方法,就是使用自定义信号来实现,新建一个窗口类MyWidget,并增加一个信号函数,在构造函数中将按钮与自定义信号建立联系,然后在另一个窗口类的构造函数中,新建一个MyWidget对象,然后建立两个窗口的联系,这个用来练习自定义信号函数。

3 第一种方法

widget.h内容如下:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include "QPushButton"

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

    Widget(const Widget& w2, QWidget *parent = nullptr);

public:
    QPushButton * btn;
};
#endif // WIDGET_H

widget.cpp内容如下,为什么用lambda表达式不行,我想了很久都不知道,最后没有使用lambda表达式,不过后面我找到原因了,就是const,具体问题可以看注释:

#include "widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    btn = new QPushButton("button", this);
    btn->move(300, 300);
}

Widget::~Widget()
{
}

Widget::Widget(const Widget& another_w, QWidget *parent) : QWidget(parent)
{
    this->btn = new QPushButton("button", this);
    this->btn->move(300, 300);

    /* 
    //下面的代码为何会报错?
    connect(this->btn, &QPushButton::clicked, [=](){
        this->hide();
        another_w.show();
    });
	//another_w在lambda函数中是常对象,不能调用非常成员函数,this是常指针,因此可以调用hide
	
    //1 能不能添加mutable选项(即[=]()mutable),让another_w可以在函数内部调用show?
    //		不能,因为another_w是通过构造函数传入,它已经被声明为了const,这里用mutable会冲突
    //2 能不能在调用connect之前,对another_w先进行取址操作,然后在lambda函数内部通过指针调用show,像this一样?
    //		不能,因为another_w在传入时就已经被声明为了const,无法进行取址操作,除非修改函数声明和定义,去掉const
    */

    connect(this->btn, &QPushButton::clicked, this, &QPushButton::hide);
    connect(this->btn, &QPushButton::clicked, &another_w, &QPushButton::show);

    connect(another_w.btn, &QPushButton::clicked, &another_w, &QPushButton::hide);
    connect(another_w.btn, &QPushButton::clicked, this, &QWidget::show);
}

main.cpp内容如下:

#include "widget.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w1;
    Widget w2(w1);
    w1.setGeometry(100, 100, 600, 600);
    w1.setWindowTitle("窗口1");
    w2.setGeometry(1000, 100, 600, 600);
    w2.setWindowTitle("窗口2");

    w1.show();
    return a.exec();
}

4 第二种方法

widget.h内容:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include "QPushButton"

class widget : public QWidget
{
    Q_OBJECT
public:
    explicit widget(QWidget *parent = nullptr);

public:
    QPushButton* btn;
signals:

};

#endif // WIDGET_H

widget.cpp内容

#include "widget.h"

widget::widget(QWidget *parent) : QWidget(parent)
{
    btn = new QPushButton("button", this);
    btn->move(300, 300);
}

mainwindow.h 内容如下:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "widget.h"
class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

public:
    widget w1, w2;
};
#endif // MAINWINDOW_H

mainwindow.cpp内容如下:

#include "mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    connect(w1.btn, &QPushButton::clicked, [=](){  //如果写成 [w1, w2]企图捕获类的成员变量w1和w2,会报错
                                                    //mainwindow.cpp:6:45: error: 'w2' in capture list does not name a variable
        this->w1.hide();
        this->w2.show();
    });

    connect(w2.btn, &QPushButton::clicked, [this](){    //将this指针写到捕获参数列表时,函数内部可以直接使用成员函数和成员变量
        w2.hide();                                      //使用w2和w1,无需通过this指针
        w1.show();
    });

    w1.setGeometry(100, 100, 600, 600);
    w1.setWindowTitle("窗口1");
    w2.setGeometry(1000, 100, 600, 600);
    w2.setWindowTitle("窗口2");
}

MainWindow::~MainWindow()
{
}

main.cpp内容如下:

#include "mainwindow.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow mw;
    mw.w1.show();
    return a.exec();
}

5 第三种方法

Widget.h内容不修改,用自动生成的:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
};
#endif // WIDGET_H

然后新建一个名为MyWidget类,mywidget.h内容如下:

#ifndef MYWIDGET_H
#define MYWIDGET_H

#include <QWidget>

class MyWidget : public QWidget
{
    Q_OBJECT
public:
    explicit MyWidget(QWidget *parent = nullptr);

signals:
    void btnClicked();
};

#endif // MYWIDGET_H

mywidget.cpp内容如下:

#include "mywidget.h"
#include "QPushButton"

MyWidget::MyWidget(QWidget *parent) : QWidget(parent)
{
    //窗口设置
    this->setGeometry(100, 100, 600, 600);
    this->setWindowTitle("窗口2");

    //新建按钮
    QPushButton* btn = new QPushButton("button", this);
    btn->move(300, 300);

    //将按钮与自定义信号建立关系
    connect(this, &MyWidget::btnClicked, [=](){
        emit this->btnClicked();
    });
}

Widget.cpp内容还没介绍,刚刚只是演示了头文件,其定义如下:

#include "widget.h"
#include "mywidget.h"
#include "QPushButton"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    //窗口设置
    this->setGeometry(100, 100, 600, 600);
    this->setWindowTitle("窗口1");

    //新建按钮
    QPushButton* btn = new QPushButton("button", this);
    btn->move(300, 300);

    MyWidget* w2 = new MyWidget();
    connect(btn, &QPushButton::clicked, [=](){
        this->hide();
        w2->show();
    });

    connect(w2, &MyWidget::btnClicked, [=](){
        w2->hide();
        this->show();
    });

}

Widget::~Widget()
{
}

由于w2是顶层窗口,且开辟在堆中,因此容易出现内存泄漏,可以将其改成通过参数传入到构造函数中,也可以将其作为Widget的成员变量(将指针作为成员变量),然后在析构函数中释放,这里可以回头自己演示。

第三种方法的设计思想比较巧妙,最好学会。

  • 2
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: 在Qt实现两个页面之间的切换可以使用QStackedWidget控件和信号与槽机制。 首先,在Qt Designer中创建两个页面的界面,在QWidget或QDialog上进行设计。然后,将这两个页面界面放置在QStackedWidget控件中,将其设置为主窗口的中心布局。 接下来,在代码中定义一个QStackedWidget对象,并在主窗口的构造函数中初始化它。将两个页面添加到QStackedWidget控件中,可以使用addWidget()函数。 然后,通过添加按钮或其他交互元素,在主窗口中创建一个信号槽连接。在槽函数中,使用setCurrentIndex()函数设置QStackedWidget中当前显示的页面的索引值。 当触发按钮或交互元素的点击事件时,发送一个信号,将其与槽函数连接。在槽函数中,通过setCurrentIndex()函数将QStackedWidget中显示的页面切换到需要显示的页面。 总结起来,通过使用QStackedWidget控件和信号与槽机制,可以实现两个页面之间的切换。 ### 回答2: 要在Qt实现两个页面的来回切换,可以使用QStackedWidget控件。QStackedWidget是一个堆叠的小部件,可以在其上添加多个页面,并且只显示其中一个页面。 首先,需要创建两个QWidget页面,例如Page1和Page2。 ```c++ // 创建页面1 QWidget *page1 = new QWidget; // 创建页面2 QWidget *page2 = new QWidget; ``` 然后,将创建的页面添加到QStackedWidget中。 ```c++ QStackedWidget *stackedWidget = new QStackedWidget; stackedWidget->addWidget(page1); stackedWidget->addWidget(page2); ``` 要在页面之间进行切换,可以使用setCurrentIndex函数,通过设置页面的索引来显示不同的页面。索引从0开始,表示第一个页面。 ```c++ // 显示页面2 stackedWidget->setCurrentIndex(1); ``` 为了实现来回切换页面,可以在需要的地方调用setCurrentIndex函数来切换页面。例如,可以在按钮的点击事件中切换页面。 ```c++ connect(button1, &QPushButton::clicked, [=](){ // 切换到页面2 stackedWidget->setCurrentIndex(1); }); connect(button2, &QPushButton::clicked, [=](){ // 切换到页面1 stackedWidget->setCurrentIndex(0); }); ``` 通过这样的方式,就可以在Qt实现两个页面的来回切换了。其中,QStackedWidget控件可以方便地管理多个页面,并在需要时进行切换显示。 ### 回答3: 在Qt实现两个页面的来回切换可以使用以下方法: 1. 使用堆栈管理页面:创建一个QStackedWidget的实例来管理页面,将要切换的页面添加到堆栈中,并设置当前页面索引。可以使用信号和槽机制来触发页面切换事件,例如点击按钮切换页面。通过设置当前页面索引,可以在页面之间来回切换。 2. 使用Tab页:创建一个QTabWidget的实例来管理页面,将不同的页面添加到Tab页中。可以在Tab页上添加标签或者按钮,通过用户点击标签或者按钮来切换到不同的页面。通过设置当前活动标签页,可以在不同页面之间实现来回切换。 3. 使用StackedLayout:创建一个QStackedLayout的实例来管理页面,将要切换的页面添加到布局中。通过切换布局中的当前索引,可以实现页面之间的切换。可以使用按钮或者其他交互控件来触发页面切换事件。 以上是几种常见的在Qt实现页面来回切换的方法,可以根据具体的需求选择合适的方法来实现页面切换
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值