qt使用tab管理多个界面

该博客介绍如何在QT中利用Tab控件实现多个界面之间的切换。作者隐藏了Tab头,并强调每个Tab中的Widget需要有父类,同时利用Boost的bimap进行双向查找操作。项目在VS2010+QT5.40+Win7环境下成功编译。

1.需求

要求实现多个页面之间的切换

2.解决

打算采用tab页来管理多个页面,并隐藏tab头

3.代码

main.cpp
#include "mytab.h"
#include <QtWidgets/QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    mytab w;
    w.show();
    return a.exec();
}
mytab.h
#ifndef MYTAB_H
#define MYTAB_H

#include <QtWidgets/QMainWindow>
#include <QResizeEvent>
#include "ui_mytab.h"
#include "pagemain.h"
#include "pageend.h"
#include "pageset.h"
#include "mydefine.h"
#include <QMap>
#include <boost/bimap.hpp>

class mytab : public QMainWindow
{
    Q_OBJECT

public:
    typedef boost::bimap<E_TAB_PAGE,int> MapPageIndex;

public:
    mytab(QWidget *parent = 0);
    ~mytab();

private slots:
    void pagechange(E_TAB_PAGE page);

public:
    E_TAB_PAGE pagetype();

protected:
    virtual void resizeEvent(QResizeEvent * event);

private:
    QTabWidget              m_tabWidget;        //管理tab:“交接班”和“设置”
    PageMain                m_pageMain;         //主页面部分
    PageEnd                 m_pageEnd;          //交接部分
    PageSet                 m_pageSet;          //设置部分
    MapPageIndex            m_mapPageIndex;     //页面和tab索引进行绑定 

private:
    void init();
    void resize();

private:
    Ui::mytabClass ui;
};

#endif // MYTAB_H
mytab.cpp
#include "mytab.h"
#include <QLineEdit>
#include <QPushButton>
#include <QVBoxLayout>
#include <QSize>
#include <utility>

mytab::mytab(QWidget *parent)
    : QMainWindow(parent), m_pageMain(parent),m_pageSet(parent),m_pageEnd(parent)
{
    ui.setupUi(this);

    init();
    connect(&m_pageMain, SIGNAL(pagechange(E_TAB_PAGE)), this, SLOT(pagechange(E_TAB_PAGE)));
    connect(&m_pageEnd, SIGNAL(pagechange(E_TAB_PAGE)), this, SLOT(pagechange(E_TAB_PAGE)));
    connect(&m_pageSet, SIGNAL(pagechange(E_TAB_PAGE)), this, SLOT(pagechange(E_TAB_PAGE)));

    //这里可以发送两次信号 这样不实时
    m_pageEnd.init(this);
    m_pageMain.init(this);
    m_pageSet.init(this);
}

mytab::~mytab()
{
}

void mytab::init()
{
    //m_mapPageIndex.clear();

    //对tab进行设置下这里要
    //必须设置父类,否则tab显示为另一个窗口
    m_tabWidget.setParent(this);

    m_tabWidget.setStyleSheet(
        "QTabWidget::pane{border: 0px;}"
        "QTabWidget::tab-bar{alignment:center;}"
        "QTabBar::tab{background:transparent; color:white; min-width:30ex; min-height:10ex;}"
        "QTabBar::tab:hover{background:rgb(255, 255, 255, 100);}"
        "QTabBar::tab:selected{border-color: white;background:white;color:green;}");

    //隐藏QTabWidget,否则主窗口被覆盖
    //m_tabWidget.hide();

    //隐藏tab
    m_tabWidget.tabBar()->hide();

    //设置tab可关闭
    m_tabWidget.setTabsClosable(true);

    //添加tab
    int nindex = -1;
    nindex = m_tabWidget.addTab(&m_pageMain,tr("pagemain"));
    if (nindex != -1)
        m_mapPageIndex.insert(MapPageIndex::value_type(E_MAIN_PAGE, nindex));
        //m_mapPageIndex[E_MAIN_PAGE] = nindex;

    nindex = m_tabWidget.addTab(&m_pageSet,tr("pageset"));
    if (nindex != -1)
        m_mapPageIndex.insert(MapPageIndex::value_type(E_SET_PAGE, nindex));
        //m_mapPageIndex[E_SET_PAGE] = nindex;

    nindex = m_tabWidget.addTab(&m_pageEnd,tr("pageend"));
    if (nindex != -1)
        m_mapPageIndex.insert(MapPageIndex::value_type(E_END_PAGE, nindex));
        //m_mapPageIndex[E_END_PAGE] = nindex;

    //显示QTabWidget
    m_tabWidget.show();

    QRect rtClient = this->geometry();
    m_tabWidget.setGeometry(rtClient);
    m_pageMain.setGeometry(rtClient);   

    pagechange(E_MAIN_PAGE);
}

void mytab::resizeEvent(QResizeEvent * event)
{
    resize();
}

void mytab::resize()
{
    QSize szClient = this->size();
    m_tabWidget.setGeometry(0, 0, szClient.width(), szClient.height());
    QWidget *ptab = m_tabWidget.currentWidget();
    if (ptab != nullptr)
        ptab->setGeometry(0, 0, szClient.width(), szClient.height());
}

void mytab::pagechange(E_TAB_PAGE page)
{
    //这里查询左map
    MapPageIndex::left_const_iterator it = m_mapPageIndex.left.find(page);
    if (it != m_mapPageIndex.left.end())
    {
        m_tabWidget.setCurrentIndex(it->second);
        resize();
    }
}

E_TAB_PAGE mytab::pagetype()
{
    E_TAB_PAGE page = E_INVALID_PAGE;
    int nindex = m_tabWidget.currentIndex();
    if (nindex != -1)
    {
        MapPageIndex::right_const_iterator it = m_mapPageIndex.right.find(nindex);
        if (it != m_mapPageIndex.right.end())
            page = it->second;
    }
    return page;
}
pagemain.h
#ifndef PAGEMAIN_H
#define PAGEMAIN_H

#include <QWidget>
#include "ui_pagemain.h"
#include "mydefine.h"

class PageMain : public QWidget
{
    Q_OBJECT

public:
    PageMain(QWidget *parent = 0);
    ~PageMain();

public:
    void init(QWidget *pParent);

signals:
    void pagechange(E_TAB_PAGE page);

private slots:
    void on_endButton_clicked();
    void on_setButton_clicked();
    void on_typeButton_clicked();

private:
    Ui::PageMain ui;
    QWidget *m_pParent;
};

#endif // PAGEMAIN_H
pagemain.cpp
#include "pagemain.h"
#include "mytab.h"
#include <QMessageBox>

PageMain::PageMain(QWidget *parent)
    : QWidget(parent)
{
    ui.setupUi(this);
    m_pParent = nullptr;
}

PageMain::~PageMain()
{
}

void PageMain::on_endButton_clicked()
{
    emit this->pagechange(E_END_PAGE);
}

void PageMain::on_setButton_clicked()
{
    emit this->pagechange(E_SET_PAGE);
}

void PageMain::on_typeButton_clicked()
{
    if (m_pParent != nullptr)
    {
        E_TAB_PAGE page = ((mytab *)m_pParent)->pagetype();
        QString strMsg("");
        strMsg = QString("%1").arg(page);
        QMessageBox::information(this, "page", strMsg);
    }
}

void PageMain::init(QWidget *pParent)
{
    m_pParent = pParent;
}
mydefine.h
#ifndef MY_DEFINE_H
#define MY_DEFINE_H

typedef enum eTabPages
{
    E_MAIN_PAGE,
    E_SET_PAGE,
    E_END_PAGE,
    E_INVALID_PAGE
}E_TAB_PAGE;

#endif
PageSet和PageEnd与PageMain较为相似 不进行上传

4.备注

1.tab中的widget必须要有父类(否则可能会出现问题)
2.项目牵涉到由类型找tab索引和tab索引查找类型 故使用了boost的bimap来实现双向查找

3.在vs2010+qt5.40+win7上编译通过

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值