Qt学习笔记(2)利用StackWidget实现选项卡式页面

 学习笔记第二篇,利用Qt实现选项卡式的页面,效果如图1.1-图1.3所示。程序实现的功能是通过点击状态栏实现不同页面的切换,实际上Qt中自带有Tab选项卡式的控件,本文利用StackWidge实现类似的页面切换功能。本文的开发思路以及页面代码参考了陆文周主编的《Qt5开发及实例(第3版)》(中国工信出版社)。

 

1.1 基本信息界面

 

1.2 联系方式界面

 

1.3 详细资料界面

        本文软件的框架如图1.4所示,下面从最下层的内容开始介绍。

 

1.4 软件开发框架

        1、底层页面的构建

        最底层的页面分为三个类,基本信息(BaseInfo)类,联系方式(Contact)类以及详细资料(Detail)类,三个类均继承自QWidget类。

        (1)Class BaseInfo

        baseinfo.h

#ifndef BASEINFO_H

#define BASEINFO_H

#include <QtCore/qglobal.h>

#if QT_VERSION >= 0x050000

#include <QtWidgets/QWidget>

#else

#include <QtGui/QWidget>

#endif

#include <QLabel>

#include <QLineEdit>

#include <QComboBox>

#include <QTextEdit>

#include <QGridLayout>

#include <QPushButton>

#include <QHBoxLayout>

#include <QVBoxLayout>

#include <QPixmap>

class BaseInfo : public QWidget

{

    Q_OBJECT

public:

    explicit BaseInfo(QWidget *parent = nullptr);

signals:

public slots:

private:

    //左侧

    QLabel *UserNameLabel;                      //用户名

    QLabel *NameLabel;                          //姓名

    QLabel *SexLabel;                           //性别

    QLabel *DepartmentLabel;                    //部门

    QLabel *AgeLabel;                           //年龄

    QLabel *OtherLabel;                         //备注

    QLineEdit *UserNameLineEdit;

    QLineEdit *NameLineEdit;

    QComboBox *SexCombox;

    QTextEdit *DepartmentTextEdit;

    QLineEdit *AgeLineEdit;

    QGridLayout *LeftLayout;

    //右侧

    QLabel *HeadLabel;                          //右上角部分,头像

    QLabel *HeadIconLabel;                      //头像图标

    QPushButton *UpdateHeadBtn;                 //更新按钮

    QHBoxLayout *TopRightLayout;                //个人说明

    QLabel *IntroductionLabel;

    QTextEdit *IntroductionTextEdit;

    QVBoxLayout *RightLayout;

};

#endif // BASEINFO_H

        baseinfo.cpp

#include "baseinfo.h"

BaseInfo::BaseInfo(QWidget *parent) : QWidget(parent)

{

    //*****左侧*****

    UserNameLabel = new QLabel(tr("用户名:"));

    UserNameLineEdit = new QLineEdit;

    NameLabel = new QLabel(tr("姓名:"));

    NameLineEdit = new QLineEdit;

    SexLabel = new QLabel(tr("性别:"));

    SexCombox = new QComboBox;

    SexCombox->addItem(tr("男"));

    SexCombox->addItem(tr("女"));

    DepartmentLabel = new QLabel(tr("部门:"));

    DepartmentTextEdit = new QTextEdit;

    AgeLabel = new QLabel(tr("年龄:"));

    AgeLineEdit = new QLineEdit;

    OtherLabel = new QLabel(tr("备注:"));

    OtherLabel->setFrameStyle(QFrame::Panel | QFrame::Sunken);

    //左侧布局

    LeftLayout = new QGridLayout();

    LeftLayout->addWidget(UserNameLabel, 0, 0);

    LeftLayout->addWidget(UserNameLineEdit, 0, 1);

    LeftLayout->addWidget(NameLabel, 1, 0);

    LeftLayout->addWidget(NameLineEdit, 1, 1);

    LeftLayout->addWidget(SexLabel, 2, 0);

    LeftLayout->addWidget(SexCombox, 2, 1);

    LeftLayout->addWidget(DepartmentLabel, 3, 0);

    LeftLayout->addWidget(DepartmentTextEdit, 3, 1);

    LeftLayout->addWidget(AgeLabel, 4, 0);

    LeftLayout->addWidget(AgeLineEdit, 4, 1);

    LeftLayout->addWidget(OtherLabel, 5, 0, 1, 2);

    LeftLayout->setColumnStretch(0, 1);

    LeftLayout->setColumnStretch(1, 3);

    //*****右侧*****

    //右上方

    HeadLabel = new QLabel(tr("头像:"));

    HeadIconLabel = new QLabel;

    QPixmap icon("123.png");

    HeadIconLabel->setPixmap(icon);

    HeadIconLabel->resize(20, 20);

    UpdateHeadBtn  = new QPushButton(tr("更新"));

    //右上方布局

    TopRightLayout = new QHBoxLayout;

    TopRightLayout->setSpacing(20);

    TopRightLayout->addWidget(HeadLabel);

    TopRightLayout->addWidget(HeadIconLabel);

    //右下方

    IntroductionLabel = new QLabel(tr("个人说明:"));

    IntroductionTextEdit = new QTextEdit;

    //右下方布局

    RightLayout = new QVBoxLayout();

    RightLayout->setMargin(10);

    RightLayout->addLayout(TopRightLayout);

    RightLayout->addWidget(IntroductionLabel);

    RightLayout->addWidget(IntroductionTextEdit);

    //总布局

    QGridLayout *mainLayout = new QGridLayout(this);

    mainLayout->setMargin(15);

    mainLayout->setSpacing(10);

    mainLayout->addLayout(LeftLayout, 0, 0);

    mainLayout->addLayout(RightLayout, 0, 1);

    //mainLayout->setSizeConstraint(QLayout::SetFixedSize);

}

        (2)Class Contact

        contact.h

#ifndef CONTACT_H

#define CONTACT_H

#include <QtCore/qglobal.h>

#if QT_VERSION >= 0x050000

#include <QtWidgets/QWidget>

#else

#include <QtGui/QWidget>

#endif

#include <QLabel>

#include <QGridLayout>

#include <QLineEdit>

#include <QCheckBox>

class Contact : public QWidget

{

    Q_OBJECT

public:

    explicit Contact(QWidget *parent = nullptr);

signals:

public slots:

private:

    QLabel *EmailLabel;

    QLineEdit *EmailLineEdit;

    QLabel *AddrLabel;

    QLineEdit *AddrLineEdit;

    QLabel *CodeLabel;

    QLineEdit *CodeLineEdit;

    QLabel *MoviTelLabel;

    QLineEdit *MoviTelLineEdit;

    QCheckBox *MoviTelCheckBox;

    QLabel *ProTelLabel;

    QLineEdit *ProTelLineEdit;

    QGridLayout *mainLayout;

};

#endif // CONTACT_H

        contact.cpp

#include "contact.h"

Contact::Contact(QWidget *parent) : QWidget(parent)

{

    EmailLabel = new QLabel(tr("电子邮件:"));

    EmailLineEdit = new QLineEdit;

    AddrLabel = new QLabel(tr("联系地址:"));

    AddrLineEdit = new QLineEdit;

    CodeLabel = new QLabel(tr("邮政编码:"));

    CodeLineEdit = new QLineEdit;

    MoviTelLabel = new QLabel(tr("移动电话:"));

    MoviTelLineEdit = new QLineEdit;

    MoviTelCheckBox = new QCheckBox(tr("接收留言"));

    ProTelLabel = new QLabel(tr("办公电话:"));

    ProTelLineEdit = new QLineEdit;

    mainLayout = new QGridLayout(this);

    mainLayout->setMargin(15);

    mainLayout->setSpacing(10);

    mainLayout->addWidget(EmailLabel, 0, 0);

    mainLayout->addWidget(EmailLineEdit, 0, 1);

    mainLayout->addWidget(AddrLabel, 1, 0);

    mainLayout->addWidget(AddrLineEdit, 1, 1);

    mainLayout->addWidget(CodeLabel, 2, 0);

    mainLayout->addWidget(CodeLineEdit, 2, 1);

    mainLayout->addWidget(MoviTelLabel, 3, 0);

    mainLayout->addWidget(MoviTelLineEdit, 3, 1);

    mainLayout->addWidget(MoviTelCheckBox, 3, 2);

    mainLayout->addWidget(ProTelLabel, 4, 0);

    mainLayout->addWidget(ProTelLineEdit, 4, 1);

    mainLayout->setSizeConstraint(QLayout::SetFixedSize);

}

        (3)Class Detail

        detail.h

#ifndef DETAIL_H

#define DETAIL_H

#include <QtCore/qglobal.h>

#if QT_VERSION >= 0x050000

#include <QtWidgets/QWidget>

#else

#include <QtGui/QWidget>

#endif

#include <QLabel>

#include <QComboBox>

#include <QLineEdit>

#include <QTextEdit>

#include <QGridLayout>

class Detail : public QWidget

{

    Q_OBJECT

public:

    explicit Detail(QWidget *parent = nullptr);

signals:

public slots:

private:

    QLabel *NationalLabel;

    QComboBox *NationalComboBox;

    QLabel *ProvinceLabel;

    QComboBox *ProvinceComboBox;

    QLabel *CityLabel;

    QLineEdit *CityLineEdit;

    QLabel *IntroductLabel;

    QTextEdit *IntroductTextEdit;

    QGridLayout *mainLayout;

};

#endif // DETAIL_H

        detail.cpp

#include "detail.h"

Detail::Detail(QWidget *parent) : QWidget(parent)

{

    NationalLabel = new QLabel(tr("国家/地址:"));

    NationalComboBox = new QComboBox;

    NationalComboBox->insertItem(0, tr("中国"));

    NationalComboBox->insertItem(1, tr("美国"));

    NationalComboBox->insertItem(2, tr("英国"));

    ProvinceLabel = new QLabel(tr("省份:"));

    ProvinceComboBox = new QComboBox;

    ProvinceComboBox->insertItem(0, tr("江苏省"));

    ProvinceComboBox->insertItem(1, tr("山东省"));

    ProvinceComboBox->insertItem(2, tr("浙江省"));

    CityLabel = new QLabel(tr("城市:"));

    CityLineEdit = new QLineEdit;

    IntroductLabel = new QLabel(tr("个人说明:"));

    IntroductTextEdit = new QTextEdit;

    mainLayout = new QGridLayout(this);

    mainLayout->setMargin(15);

    mainLayout->setSpacing(10);

    mainLayout->addWidget(NationalLabel, 0, 0);

    mainLayout->addWidget(NationalComboBox, 0, 1);

    mainLayout->addWidget(ProvinceLabel, 1, 0);

    mainLayout->addWidget(ProvinceComboBox, 1, 1);

    mainLayout->addWidget(CityLabel, 2, 0);

    mainLayout->addWidget(CityLineEdit, 2, 1);

    mainLayout->addWidget(IntroductLabel, 3, 0);

    mainLayout->addWidget(IntroductTextEdit, 3, 1);

}

        2、将底层页面放在QStackWidget中

        新建一个Content类,继承自QFrame。在Content类中,创建一个QStackWidget对象,然后将上述三个页面插入到此对象中。

        content.h

#ifndef CONTENT_H

#define CONTENT_H

#include <QtCore/qglobal.h>

#if QT_VERSION >= 0x050000

#include <QtWidgets/QWidget>

#else

#include <QtGui/QWidget>

#endif

#include <QFrame>

#include <QStackedWidget>

#include <QGridLayout>

#include "baseinfo.h"

#include "contact.h"

#include "detail.h"

class Content : public QFrame

{

    Q_OBJECT

public:

    explicit Content(QWidget *parent = nullptr);

    QStackedWidget *stack;

    BaseInfo *baseInfo;

    Contact *contact;

    Detail *detail;

signals:

public slots:

private:

    QGridLayout *mainLayout;

};

#endif // CONTENT_H

        content.cpp

        这里用了一个QGridLayou布局,布局中只有一个QStackWidget。如果去掉此布局,则在主界面中的Stack页面无法随主界面变化,只能保持同一个尺寸,所以这里有必要加一个布局。

#include "content.h"

Content::Content(QWidget *parent) : QFrame(parent)

{

    stack = new QStackedWidget(this);                           //创建一个堆栈窗口对象

    stack->setFrameStyle(QFrame::Panel | QFrame::Raised);       //窗口的显示风格

    //插入页面

    baseInfo = new BaseInfo();

    contact = new Contact();

    detail = new Detail();

    stack->addWidget(baseInfo);

    stack->addWidget(contact);

    stack->addWidget(detail);

    mainLayout = new QGridLayout(this);

    mainLayout->setMargin(2);

    mainLayout->addWidget(stack, 0, 0);

}

        3、主界面的实现

        这里的主界面不是指main函数,而是指QMainWindow,主界面的类为MainStack继承自QMainWindow。在主界面上主要实现的功能是状态栏和Stack界面的显示以及它们之间的连接。

        mainstack.h

#ifndef MAINSTACK_H

#define MAINSTACK_H

#include <QMainWindow>

#include <QToolBar>

#include <QAction>

#include <QGridLayout>

#include "content.h"

class MainStack : public QMainWindow

{

    Q_OBJECT

public:

    MainStack(QWidget *parent = 0);

    ~MainStack();

    Content *content;

    QGridLayout *mainLayout;

    void createAction();                                //动作处理函数

    void createToolBar();                               //创建工具栏

private:

    QToolBar *stackTool;                                //工具栏

    QAction *openStack[3];

private slots:

    void openBaseInfo();                                //点击状态栏的槽函数

    void openContact();

    void openDtail();

};

#endif // MAINSTACK_H

        mainstack.cpp

        主界面的中心部件就一个,就不加布局了,所有的布局都加在上一步的QFrame中。

#include "mainstack.h"

MainStack::MainStack(QWidget *parent)

    : QMainWindow(parent)

{

    setWindowTitle(tr("主界面"));

    setMinimumSize(800, 480);

    createAction();

    createToolBar();

    content = new Content(this);

    setCentralWidget(content);                              //将stack窗口设置为中心部件

    //mainLayout = new QGridLayout(this);

    //mainLayout->setMargin(15);

    //mainLayout->setSpacing(10);

    //mainLayout->addWidget(stackTool, 0, 0);

    //mainLayout->addWidget(content, 1, 0);

}

MainStack::~MainStack()

{

}

//Action动作

void MainStack::createAction()

{

    //转到第一个界面

    openStack[0] = new QAction(tr("基本信息"), this);

    openStack[0]->setShortcut(tr("Ctrl+Q"));

    openStack[0]->setStatusTip(tr("界面1"));

    connect(openStack[0], SIGNAL(triggered(bool)), this, SLOT(openBaseInfo()));

    //转到第二个界面

    openStack[1] = new QAction(tr("联系方式"), this);

    openStack[1]->setShortcut(tr("Ctrl+W"));

    openStack[1]->setStatusTip(tr("界面2"));

    connect(openStack[1], SIGNAL(triggered(bool)), this, SLOT(openContact()));

    //转到第三个界面

    openStack[2] = new QAction(tr("详细资料"), this);

    openStack[2]->setShortcut(tr("Ctrl+E"));

    openStack[2]->setStatusTip(tr("界面3"));

    connect(openStack[2], SIGNAL(triggered(bool)), this, SLOT(openDtail()));

}

//创建工具栏

void MainStack::createToolBar()

{

    stackTool = addToolBar("工具栏");

    stackTool->addAction(openStack[0]);

    stackTool->addAction(openStack[1]);

    stackTool->addAction(openStack[2]);

}

//转到界面1槽函数

void MainStack::openBaseInfo()

{

    this->content->stack->setCurrentIndex(0);

}

//转到界面2槽函数

void MainStack::openContact()

{

    this->content->stack->setCurrentIndex(1);

}

//转到界面3槽函数

void MainStack::openDtail()

{

    this->content->stack->setCurrentIndex(2);

}

        4、main函数

        main函数就是显示主界面。

#include "mainstack.h"

#include <QApplication>

int main(int argc, char *argv[])

{

    QApplication a(argc, argv);

    MainStack w;

    w.show();

    return a.exec();

}

原文地址:https://www.cnblogs.com/bruce1992/p/14311392.html