1.用继承pushbutton派生类来实现tab按钮,里面加一个QPushbutton关闭按钮;(自定义类:CCustomTabButton)

2.多个tab按钮用QHboxLayout做容器;

3.用QStackLayout做page容易,保存tab页的widget;

4.从QWidget继承类CCustomTabWidget组合tabbar和page

5.用qss渲染tarbar的效果;

#ifndef CCUSTOMTABWIDGET_H
#define CCUSTOMTABWIDGET_H #include <QPushButton>
#include <QList> class QLabel;
class QStackedLayout;
class QHBoxLayout; class CCustomTabButton :public QPushButton
{
Q_OBJECT
public:
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_OBJECT
public:
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<CCustomTabButton *> m_listTabButton;
QHBoxLayout *m_hlTabbar;
QLabel *m_lblTabbar;
QStackedLayout *m_stackWidget;
int m_nCurrentIndex;
}; #endif // CCUSTOMTABWIDGET_H
#include "ccustomtabwidget.h"
#include <QPushButton>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QLabel>
#include <QStackedLayout>
#include <QDebug>
#include <QStyleOption>
#include <QPainter> 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!!!"<<nIndex;
return;
} this->RemoveTab(nIndex);
} void CCustomTabWidget::on_tabbar_clicked(int nIndex)
{
if (nIndex < 0 || nIndex >= m_listTabButton.size())
{
qDebug()<<"CCustomTabWidget::on_tabbar_clicked error!!!"<<nIndex;
return;
} this->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!!!"<<index;
return;
} CCustomTabButton *btn = m_listTabButton.at(index);
m_hlTabbar->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!!!"<<index;
return;
} m_nCurrentIndex = index;
if (m_listTabButton.size() == 1)
{
m_lblTabbar->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:"<<i;
}
else
{
m_listTabButton.at(i)->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下载地址:

http://download.csdn.net/detail/lanhy999/6386437

QT下自定义QQ聊天窗口tab控件的更多相关文章

  1. 【Qt】仿QQ表情选择控件

         表情选择控件在聊天应用中常常要用到,做起来尽管不复杂可是非常繁琐.特别是有些图标须要按顺序排列.每次重做必定是非常费时.所以我将聊天表情选择控件封装成一个独立的类QFaceSelectWid ...

  2. WPF下可编辑Header的Tab控件实现

    介绍 有这样一个需求,当用户双击Tab控件Header区域时, 希望可以直接编辑.对于WPF控件,提供一个ControlTemplate在加上一些Trigger就可以实现.效果如下: 代码 首先,我们 ...

  3. Qt编写自定义控件31-面板仪表盘控件

    一.前言 在Qt自定义控件中,仪表盘控件是数量最多的,写仪表盘都写到快要吐血,可能是因为各种工业控制领域用的比较多吧,而且仪表盘又是比较生动直观的,这次看到百度的echart中有这个控件,所以也来模仿 ...

  4. android - 自定义(组合)控件 + 自定义控件外观

    转载:http://www.cnblogs.com/bill-joy/archive/2012/04/26/2471831.html android - 自定义(组合)控件 + 自定义控件外观   A ...

  5. WPF自定义LED风格数字显示控件

    原文:WPF自定义LED风格数字显示控件 版权声明:本文为博主原创文章,转载请注明作者和出处 https://blog.csdn.net/ZZZWWWPPP11199988899/article/de ...

  6. 【C#】wpf自定义calendar日期选择控件的样式

    原文:[C#]wpf自定义calendar日期选择控件的样式 首先上图看下样式 原理 总览 ItemsControl内容的生成 实现 界面的实现 后台ViewModel的实现 首先上图,看下样式 原理 ...

  7. 获取 AlertDialog自定义的布局 的控件

    AlertDialog自定义的布局 效果图: 创建dialog方法的代码如下: 1 LayoutInflater inflater = getLayoutInflater(); 2 View layo ...

  8. 扩展easyUI tab控件,添加加载遮罩效果

    项目里要用HighChart显示图表,如果返回的数量量太多,生成图表是一个很耗时的过程.tab控件又没有显示遮罩的设置(至少本菜是没有找到), Google了一下,根据另一个兄台写的方法,拿来改造了一 ...

  9. NVelocity+Bootstrap tab控件 异常之

    异常信息:Encountered "tings" at line 54, column 55.Was expecting one of:   "(" ...   ...

随机推荐

  1. RTMP

    实时消息传输协议 RTMP(Real Time Messaging Protocol) http://blog.csdn.net/defonds/article/details/17403225 译序 ...

  2. 164. Maximum Gap

    题目: Given an unsorted array, find the maximum difference between the successive elements in its sort ...

  3. 转:为什么Eclipse中 按 F3 无效

    通常是由于自己的 工程 建得不对, 没有声明为 JAVA 或 PHP 类型工程. 例如, PHP 工程的 .project 文件中的内容如果如下, F3 应该就可以起作用了. <?xml ver ...

  4. Oracle系列之表空间

    涉及到表的处理请参看原表结构与数据  Oracle建表插数据等等 创建表空间等等 select tablespace_name from dba_tablespaces;--dba权限用户查询数据库中 ...

  5. bzoj1103

    其实这道题和以前在poj上做过的将树映射到树状数组的题目很像 首先不难想到,将一条边从土路修成公路,只对以这条边连接的孩子结点为根的子树有影响: 于是和之前那道poj的题目很像,后序遍历树,对每个节点 ...

  6. BZOJ_2049_[Sdoi_2008]_Cave_洞穴勘测_(LCT/并查集)

    描述 http://www.lydsy.com/JudgeOnline/problem.php?id=2049 给出一个森林,起始互不相连,现在有link和cut两种操作,问x,y是否在一棵树里. 分 ...

  7. PHP 'ext/gd/gd.c' gdImageCrop整数符号错误漏洞

    漏洞版本: PHP 5.5.x 漏洞描述: CVE ID:CVE-2013-7328 PHP是一种HTML内嵌式的语言. PHP 'ext/gd/gd.c' gdImageCrop函数存在多个整数符号 ...

  8. How to: Hide the Ribbon in SharePoint 2010

    转:http://blogs.msdn.com/b/sharepointdev/archive/2012/04/30/how-to-hide-the-ribbon-in-sharepoint-2010 ...

  9. 用PowerShell批量收回wsp包

    转:http://www.xuebuyuan.com/168334.html 提供wsp部署的参数:$wspnames:路径下的所有wsp文件名用逗号隔开,如"sumhtestwsp.wsp ...

  10. hadoop学习笔记——基础知识及安装

    1.核心 HDFS  分布式文件系统    主从结构,一个namenoe和多个datanode, 分别对应独立的物理机器 1) NameNode是主服务器,管理文件系统的命名空间和客户端对文件的访问操 ...