QT下自定义QQ聊天窗口tab控件
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控件的更多相关文章
- 【Qt】仿QQ表情选择控件
表情选择控件在聊天应用中常常要用到,做起来尽管不复杂可是非常繁琐.特别是有些图标须要按顺序排列.每次重做必定是非常费时.所以我将聊天表情选择控件封装成一个独立的类QFaceSelectWid ...
- WPF下可编辑Header的Tab控件实现
介绍 有这样一个需求,当用户双击Tab控件Header区域时, 希望可以直接编辑.对于WPF控件,提供一个ControlTemplate在加上一些Trigger就可以实现.效果如下: 代码 首先,我们 ...
- Qt编写自定义控件31-面板仪表盘控件
一.前言 在Qt自定义控件中,仪表盘控件是数量最多的,写仪表盘都写到快要吐血,可能是因为各种工业控制领域用的比较多吧,而且仪表盘又是比较生动直观的,这次看到百度的echart中有这个控件,所以也来模仿 ...
- android - 自定义(组合)控件 + 自定义控件外观
转载:http://www.cnblogs.com/bill-joy/archive/2012/04/26/2471831.html android - 自定义(组合)控件 + 自定义控件外观 A ...
- WPF自定义LED风格数字显示控件
原文:WPF自定义LED风格数字显示控件 版权声明:本文为博主原创文章,转载请注明作者和出处 https://blog.csdn.net/ZZZWWWPPP11199988899/article/de ...
- 【C#】wpf自定义calendar日期选择控件的样式
原文:[C#]wpf自定义calendar日期选择控件的样式 首先上图看下样式 原理 总览 ItemsControl内容的生成 实现 界面的实现 后台ViewModel的实现 首先上图,看下样式 原理 ...
- 获取 AlertDialog自定义的布局 的控件
AlertDialog自定义的布局 效果图: 创建dialog方法的代码如下: 1 LayoutInflater inflater = getLayoutInflater(); 2 View layo ...
- 扩展easyUI tab控件,添加加载遮罩效果
项目里要用HighChart显示图表,如果返回的数量量太多,生成图表是一个很耗时的过程.tab控件又没有显示遮罩的设置(至少本菜是没有找到), Google了一下,根据另一个兄台写的方法,拿来改造了一 ...
- NVelocity+Bootstrap tab控件 异常之
异常信息:Encountered "tings" at line 54, column 55.Was expecting one of: "(" ... ...
随机推荐
- unity 基础之PhysicsManager
原地址:http://www.cnblogs.com/alongu3d/p/3644725.html @by 广州小龙 1.Gravity(重力) 物理系统都是根据实际情况进行模拟的,由于Y值是往下 ...
- Jmeter 日志设置---如何设置java协议中被测jar的日志?
先转载一下Jmeter的日志设置: Jmeter运行出现问题可以通过调整jmeter的日志级别定位问题,但运行测试时建议关闭jmeter日志,jmeter打印日志耗费系统性能. Jmeter日志默认存 ...
- ZOJ 3817 Chinese Knot
题意:给定4个长度为N的字符串( N <= 100000),然后构成一个“中国结”,给定目标串,问能否从某个节点出发走一遍得到目标串,其中不能连续通过3个中心节点,也就是从字符串一个端点转移到其 ...
- cocos2d-x mac or windows eclipse android ------ Eclipse工程里面还会有许多警告
由于公司的游戏项目比较特殊, coco2d-x 的 ios 和 android 的游戏 代码 没有采用 共享目录的开发方式.所以android 内的 c++ 游戏代码全部放在 jni 下, ...
- POJ 1840 Eps 解题报告(哈希)
a1x13+ a2x23+ a3x33+ a4x43+ a5x53=0,xi∈[-50,50],且xi!=0.让我们求所有解的可能. 首先,如果暴力判断的话,每个x的取值有100种可能,100^5肯定 ...
- POJ 1860 Currency Exchange + 2240 Arbitrage + 3259 Wormholes 解题报告
三道题都是考察最短路算法的判环.其中1860和2240判断正环,3259判断负环. 难度都不大,可以使用Bellman-ford算法,或者SPFA算法.也有用弗洛伊德算法的,笔者还不会SF-_-…… ...
- apache开源项目--Cassandra
Apache Cassandra是一套开源分布式Key-Value存储系统.它最初由Facebook开发,用于储存特别大的数据.Facebook目前在使用此系统. 主要特性: 分布式 基于column ...
- 【转】 Java虚拟机内存的堆区(heap),栈区(stack)和静态区(static/method)
JAVA的JVM的内存可分为3个区:堆(heap).栈(stack)和方法区(method) 堆区:1.存储的全部是对象,每个对象都包含一个与之对应的class的信息.(class的目的是得到操作指令 ...
- .Net 提交页面,js修改的Label值会丢掉
<head id="Head1" runat="server"> <script src="../Jquery/jquery-1.1 ...
- POJ --- 2918 求解数独
Tudoku Description Tom is a master in several mathematical-theoretical disciplines. He recently fo ...