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();
}

        至此整个工程创建完毕,此工程只是一个页面切换的框架,具体的功能需要后续进行添加。
  • 22
    点赞
  • 87
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值