2.多个tab按钮用QHboxLayout做容器;
3.用QStackLayout做page容易,保存tab页的widget;
4.从QWidget继承类CCustomTabWidget组合tabbar和page
5.用qss渲染tarbar的效果;
#ifndef CCUSTOMTABWIDGET_H#define CCUSTOMTABWIDGET_H#include#include class QLabel;class QStackedLayout;class QHBoxLayout;class CCustomTabButton :public QPushButton{ Q_OBJECTpublic: explicit CCustomTabButton(QWidget *parent = 0); ~CCustomTabButton(); void setText(QString text); void setIndex(int nIndex){ m_nIndex = nIndex; } int getIndex(){ return m_nIndex; }signals: void clicked(int nIndex); void closeClicked(int nIndex);protected: void resizeEvent(QResizeEvent * event); void mousePressEvent(QMouseEvent * event); void enterEvent(QEvent * event ); void leaveEvent(QEvent * event );private slots: void on_btnClose_clicked();private: QPushButton * m_btnClose; int m_nIndex; };class CCustomTabWidget : public QWidget{ Q_OBJECTpublic: explicit CCustomTabWidget(QWidget *parent = 0); ~CCustomTabWidget(); void AddTab(QString title, QWidget *widget); void RemoveTab(int index); void Clear(); void SetCurrentWidget(QWidget *widget); void SetCurrentIndex(int index); int CurrentIndex(); int count() { return m_listTabButton.count(); } QWidget* widget(int nIndex);protected: void paintEvent(QPaintEvent *);signals:private slots: void on_tabbar_closeClicked(int nIndex); void on_tabbar_clicked(int nIndex);private: QList m_listTabButton; QHBoxLayout *m_hlTabbar; QLabel *m_lblTabbar; QStackedLayout *m_stackWidget; int m_nCurrentIndex;};#endif // CCUSTOMTABWIDGET_H
#include "ccustomtabwidget.h"#include#include #include #include #include #include #include #include CCustomTabButton::CCustomTabButton(QWidget *parent): QPushButton(parent){ this->setCheckable(true); m_btnClose = new QPushButton(this); m_btnClose->setObjectName(QString::fromUtf8("CCustomTabCloseButton")); m_btnClose->setVisible(false); m_btnClose->setGeometry(QRect(this->width()-16,0,16,16)); connect(m_btnClose, SIGNAL(clicked()), this, SLOT(on_btnClose_clicked()));}CCustomTabButton::~CCustomTabButton(){ delete m_btnClose;}void CCustomTabButton::resizeEvent(QResizeEvent * event){ m_btnClose->setGeometry(QRect(this->width()-16,0,16,16));}void CCustomTabButton::mousePressEvent(QMouseEvent * event){ emit clicked(m_nIndex);}void CCustomTabButton::enterEvent ( QEvent * event ){ QPushButton::enterEvent(event); m_btnClose->setVisible(true);}void CCustomTabButton::leaveEvent ( QEvent * event ){ QPushButton::leaveEvent(event); m_btnClose->setVisible(false);}void CCustomTabButton::on_btnClose_clicked(){ emit closeClicked(m_nIndex);}void CCustomTabButton::setText(QString text){ QPushButton::setText(text); this->setToolTip(text);}/*** CCustomTabWidget**/CCustomTabWidget::CCustomTabWidget(QWidget *parent) : QWidget(parent){ QVBoxLayout *vlMain = new QVBoxLayout(); vlMain->setSpacing(0); vlMain->setMargin(0); this->setLayout(vlMain); m_lblTabbar = new QLabel(); m_lblTabbar->setObjectName(QString::fromUtf8("CCustomTabBar")); m_hlTabbar = new QHBoxLayout(); m_hlTabbar->setSpacing(0); m_hlTabbar->setMargin(0); m_hlTabbar->setContentsMargins(5,0,5,0); m_hlTabbar->addStretch(); m_lblTabbar->setLayout(m_hlTabbar); vlMain->addWidget(m_lblTabbar); m_stackWidget = new QStackedLayout(); vlMain->addLayout(m_stackWidget);}CCustomTabWidget::~CCustomTabWidget(){ for (int i = 0; i < m_listTabButton.size(); i++) { delete m_listTabButton.at(i); } m_listTabButton.clear(); for (int i = 0; i < m_stackWidget->count(); i++) { delete m_stackWidget->widget(i); } delete m_lblTabbar; delete m_stackWidget;}void CCustomTabWidget::paintEvent(QPaintEvent *){ QStyleOption opt; opt.init(this); QPainter p(this); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);}void CCustomTabWidget::on_tabbar_closeClicked(int nIndex){ if (nIndex < 0 || nIndex >= m_listTabButton.size()) { qDebug()<<"CCustomTabWidget::on_tabbar_closeClicked error!!!"< RemoveTab(nIndex);}void CCustomTabWidget::on_tabbar_clicked(int nIndex){ if (nIndex < 0 || nIndex >= m_listTabButton.size()) { qDebug()<<"CCustomTabWidget::on_tabbar_clicked error!!!"< SetCurrentIndex(nIndex);}QWidget* CCustomTabWidget::widget(int nIndex){ if (nIndex < 0 || nIndex >= m_listTabButton.size()) { return NULL; } return m_stackWidget->widget(nIndex);}void CCustomTabWidget::AddTab(QString title, QWidget *widget){ CCustomTabButton *btn = new CCustomTabButton(); btn->setObjectName(QString::fromUtf8("CCustomTabButton")); connect(btn, SIGNAL(clicked(int)), this, SLOT(on_tabbar_clicked(int))); connect(btn, SIGNAL(closeClicked(int)), this, SLOT(on_tabbar_closeClicked(int))); btn->setText(title); int nIndex = m_listTabButton.size(); btn->setIndex(nIndex); m_hlTabbar->insertWidget(nIndex,btn); m_listTabButton.append(btn); m_stackWidget->addWidget(widget); this->SetCurrentIndex(nIndex);}void CCustomTabWidget::RemoveTab(int index){ if (index < 0 || index >= m_listTabButton.size()) { qDebug()<<"CCustomTabWidget::RemoveTab error!!!"< removeWidget(btn); m_listTabButton.removeAt(index); delete btn; QWidget * widget = m_stackWidget->widget(index); m_stackWidget->removeWidget(widget); delete widget; if (m_listTabButton.size() > 0) { int nCurrIndex = index-1 >= 0?index-1 :0; this->SetCurrentIndex(nCurrIndex); }}void CCustomTabWidget::Clear(){ for (int i = 0; i < m_listTabButton.size(); i++) { m_hlTabbar->removeWidget(m_listTabButton.at(i)); delete m_listTabButton.at(i); } m_listTabButton.clear(); for (int i = 0; i < m_stackWidget->count(); i++) { QWidget *widget = m_stackWidget->widget(0); m_stackWidget->removeWidget(widget); delete widget; }}void CCustomTabWidget::SetCurrentWidget(QWidget *widget){ if (widget == NULL) { return; } for (int i = 0; i < m_stackWidget->count(); i++) { if(m_stackWidget->widget(i) == widget) { this->SetCurrentIndex(i); break; } }}void CCustomTabWidget::SetCurrentIndex(int index){ if (index < 0 || index >= m_listTabButton.size()) { qDebug()<<"CCustomTabWidget::SetCurrentTab error!!!"< setVisible(false); } else { m_lblTabbar->setVisible(true); } for (int i = 0; i < m_listTabButton.size(); i++) { m_listTabButton.at(i)->setIndex(i); m_listTabButton.at(i)->setVisible(true); if (i == m_nCurrentIndex) { m_listTabButton.at(i)->setChecked(true); qDebug()<<"checked:"< setChecked(false); } } m_stackWidget->setCurrentIndex(m_nCurrentIndex);}int CCustomTabWidget::CurrentIndex(){ return m_nCurrentIndex;}
#CCustomTabButton {max-height:30px; min-height:20px; border-image: url(:/skin/skin/tab_btn_bg_normal.png) 8 8 2 4; border-width:8px 8px 2px 4px;background-color: transparent;color:black;} " "#CCustomTabButton:hover {border-image: url(:/skin/skin/tab_btn_bg_hover.png) 8 8 4 4; border-width:8px 8px 4px 4px;} " "#CCustomTabButton:checked {border-image: url(:/skin/skin/tab_btn_bg_checked.png) 8 8 2 4; border-width:8px 8px 2px 4px;} " "#CCustomTabCloseButton{border-image: url(:/skin/skin/tab_btn_close_normal.png);}" "#CCustomTabCloseButton:hover{border-image: url(:/skin/skin/tab_btn_close_hover.png);}" "#CCustomTabBar{min-height:30px;background:transparent;border-bottom:1px solid #cacaca; } " "CCustomTabWidget{border-image: url(:/skin/skin/tab_bg1.png) 30; border-width:30px;}
Demo下载地址: