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. android 发送自定义广播以及接收自定义广播

    发送自定义广播程序: 布局文件: <?xml version="1.0" encoding="utf-8"?> <LinearLayout x ...

  2. Tomcat 6 支持 NIO -- Tomcat的四种基于HTTP协议的Connector性能比较(转载)

    Tomcat从5.5版本开始,支持以下四种Connector的配置分别为: <Connector port="8081" protocol="org.apache. ...

  3. linux是实时系统还是分时操作系统

    实时操作系统 实时操作系统 英文称Real Time Operating System,简称RTOS. 1.实时操作系统定义 实时操作系统(RTOS)是指当外界事件或数据产生时,能够接受并以足够快的速 ...

  4. thinkphp 模板替换

    具体详见tp手册. 如果需要修改模板替换映射路径. 则需: 'TMPL_PARSE_STRING'=>array( '__PUBLIC__'=>__ROOT__.'/'.APP_NAME. ...

  5. 用Unity3.0+MVC4搭建项目

    新年快乐!又是新的一年到来了,我好久没有在园子里面做笔记啦,由于工作上的事,还好年前把该做的都完善了,于是就写了辞职信.由于家庭原因,不得不离职,在春节期间呢,我放松了几天,去这里去那里的,朋友们喜欢 ...

  6. 【Quick 3.3】资源脚本加密及热更新(三)热更新模块

    [Quick 3.3]资源脚本加密及热更新(三)热更新模块 注:本文基于Quick-cocos2dx-3.3版本编写 一.介绍 lua相对于c++开发的优点之一是代码可以在运行的时候才加载,基于此我们 ...

  7. IIS UrlWriter配置(asp.net)

    前提在建虚拟目录或网站时注意以下设置第一步:下载URLRewriter 添加URLRewriter和ActionlessForm(不添加只能在VS实现,IIS下会找不到页面). 第二步:配置web.c ...

  8. 放在jsp头部的代码

    String path = request.getContextPath(); String basePath = request.getScheme()+"://"+reques ...

  9. Azure Site Recovery 通过一键式流程将虚拟机故障转移至 Azure虚拟机

    Ruturaj Dhekane 云 + Enterprise 项目经理  现在,AzureSite Recovery可以通过其"灾难恢复至 Azure"功能保护您的工作负荷,并 ...

  10. Xcode6 运行程序后,右侧Debug区域的Memory显示空白解决方法

    http://chenyh-blog.com/%E8%9B%8B%E7%96%BC%E7%9A%84%E5%86%85%E5%AD%98-%E7%AC%AC%E4%B8%89%E7%AF%87-sdw ...