Qt 系列(四)——界面切换

前言

上一篇大致过完窗体,这篇聊下界面的切换,毕竟不管哪个应用一般都不会是单页面。

界面切换

界面切换在我个人用的过程中,有几个方式可以分享下。

  • Widget 的显示隐藏,在上一篇聊 Widget 的时候应该还有印象是啥效果
  • TabWidget,通过选项卡的方式切换界面
  • StackedWidget,类似选项卡,不过没有 tab 按钮,推荐是使用这种。

我们来看下几种方式的实现过程以及效果。

准备工作:新建工程选择 MainWindow,然后新建三个 Widget 作为单页。

主窗体 ui 设置如下图所示。

主窗体界面

Widget 显示隐藏

首先实例化对应的 Widget 这个就不多说了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// .h
#include "Widget1.h"
#include "Widget2.h"
#include "Widget3.h"

public:
QtDemo(QWidget *parent = Q_NULLPTR);

private:
void init();

private:
Ui::QtDemoClass ui;

Widget1* m_widget1;
Widget2* m_widget2;
Widget3* m_widget3;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// .cpp
QtDemo::QtDemo(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
init();
}

void QtDemo::init()
{
m_widget1 = new Widget1(ui.groupBox);
m_widget2 = new Widget2(ui.groupBox);
m_widget3 = new Widget3(ui.groupBox);

m_widget2->hide();
m_widget3->hide();
}

运行之后可以自己看下效果,也可以自己做个测试,如果那两个没有隐藏,效果是啥样(最好给三个界面的 label 位置调整下,可以看的更明显),当然这个不是说明三个 widget 是同层,实际还是不同的层,只是每个 Widget 的内容比较单一,如果设置了背景色就能看出来还是会存在遮挡的,不设置图层的话,一般都是按照 new 的先后顺序,先放的肯定是在最下面。

我们来设置下按钮事件来做切换,这里捎带聊下 qt 的事件机制,也就是信号、槽。

信号、槽

信号槽的模式类似于事件委托,也有点儿像观察者模式,即一方发出信号,由已注册的另一方根据信号做对应事件的响应与处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
static QMetaObject::Connection connect(const QObject *sender, const char *signal,
const QObject *receiver, const char *member, Qt::ConnectionType = Qt::AutoConnection);

static QMetaObject::Connection connect(const QObject *sender, const QMetaMethod &signal,
const QObject *receiver, const QMetaMethod &method,
Qt::ConnectionType type = Qt::AutoConnection);

inline QMetaObject::Connection connect(const QObject *sender, const char *signal,
const char *member, Qt::ConnectionType type = Qt::AutoConnection) const;
// qt5以后新增
static inline QMetaObject::Connection connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal,
const typename QtPrivate::FunctionPointer<Func2>::Object *receiver, Func2 slot,
Qt::ConnectionType type = Qt::AutoConnection)

通过这几个方法可以实现事件的绑定,发送方->接收方(通过哪种信号,以及接收方处理的方法)。

信号槽的特点如下:

  • 一个信号可以绑定多个槽
  • 多个信号可以绑定一个槽
  • 一个信号可以关联到另一个信号
  • 一个信号可以关联到多个信号

回归到我们第一个实现方式的编码来,在头文件新加几个按钮点击的方法(注意 btn3 的事件没有在 slots 标签下)。

1
2
3
4
5
6
7
8
9
// .h
public:
QtDemo(QWidget *parent = Q_NULLPTR);

void btnWidget3Clicked();

public slots:
void btnWidget1Clicked();
void btnWidget2Clicked();

在 cpp 中实现对应的方法事件,同样留意 btn3 的写法(qt5 以上可以这样使用)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// .cpp

void QtDemo::btnWidget1Clicked()
{
m_widget1->show();
m_widget2->hide();
m_widget3->hide();
}

void QtDemo::btnWidget2Clicked()
{
m_widget1->hide();
m_widget2->show();
m_widget3->hide();
}

void QtDemo::btnWidget3Clicked()
{
m_widget1->hide();
m_widget2->hide();
m_widget3->show();
}

void QtDemo::setConnection()
{
connect(ui.btnWidget1, SIGNAL(clicked()), this, SLOT(btnWidget1Clicked()));
connect(ui.btnWidget2, SIGNAL(clicked()), this, SLOT(btnWidget2Clicked()));
connect(ui.btnWidget3, &QPushButton::clicked, this, &QtDemo::btnWidget3Clicked);
}

运行之后点击按钮,就实现了界面的切换。

TabWidget 实现界面切换

这个比较简单,我们可以直接通过界面直接添加 Tab Widget 组件来直接切换界面,这里我拿 widget1 做了调整。

添加TabWidget

用过选项卡的肯定都清楚,本身选项卡内就是一个个 Widget,也就相当于是一个个单独的界面。

我们也可以通过代码动态去添加已经写好的界面。

1
2
m_widget3 = new Widget3();
ui->tabWidget->addTab(m_widget3, QStringLiteral("界面3"));

StackedWidget 实现界面切换

这个堆小部件的大致用法与TabWidget类似,不过它没有选项卡的直接切换,需要通过按钮事件来自己去设置显示哪个索引下的 widget。

修改对应方法如下,每次 addWidget 相当于添加一个 Page,可以理解为存放界面的数组。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
void QtDemo::btnWidget1Clicked()
{
ui.stackedWidget->setCurrentIndex(0);
}

void QtDemo::btnWidget2Clicked()
{
ui.stackedWidget->setCurrentIndex(1);
}

void QtDemo::btnWidget3Clicked()
{
ui.stackedWidget->setCurrentIndex(2);
}

void QtDemo::init()
{
m_widget1 = new Widget1();
m_widget2 = new Widget2();
m_widget3 = new Widget3();

ui.stackedWidget->addWidget(m_widget1);
ui.stackedWidget->addWidget(m_widget2);
ui.stackedWidget->addWidget(m_widget3);

setConnection();
}

小结

界面切换暂时就聊这么多,这仅是个人使用过程中总结的,可能不是太合适,不过效果跟预期还是一样的,建议使用 StackedWidget 来实现界面的切换,当然 TabWidget 去了 tab 跟这个显示的就基本一样了,这种相对来说维护方便些,切换只需要设置对应的索引显示就行,同第一种比较还是便利许多(毕竟第一种如果界面多了,那每次显示隐藏都要写一堆)。


Qt 系列(四)——界面切换
http://www.aprilblank.top/qt/change_page.html
作者
AprilBlank
发布于
2022年6月25日
许可协议