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: "(" ... ...
随机推荐
- 服务器部署_nginx的host not found in upstream "tomcat_www.bojinne" 错误解决办法
今天修改了nginx.conf之后,nginx-t报错. 1. 网上多认为此错误需要修改/etc/hosts,添加该域名对应的ip 2. 我自己的解决方案是仔细核对 upstream 后面的字符 和 ...
- Android EditText多行显示及所有属性
android:id="@+id/editSms" android:layout_width="fill_parent" android:layout_heig ...
- Eclipse中输入系统变量和运行参数
在开发时,有时候可能需要根据不同的环境设置不同的系统参数,我们都知道,在使用java -jar命令时可以使用-D参数来设置运行时的系统变量,同样,在Eclipse中运行java程序时,我们怎么设置该系 ...
- MySQL information_schema表查询导致内存暴涨
case:下面的一条sql语句,导致mysql实例内存暴涨: select * from tables where table_name not in(select table_name from p ...
- 函数 flst_get_first
/********************************************************************//** Gets list first node addre ...
- Matlab read_grib.r4 安装新方法(转自:http://blog.sina.com.cn/s/blog_9f36648b010179s7.html)
最近,打算用Matlab处理些GRIB格式的文件,需要在Matlab中添加read_grib.m文件,其实相当于是添加一个工具箱.read_grib.m的下载见:http://www.renci.or ...
- JVM内存模型及内存分配过程
一.JVM内存模型 JVM主要管理两种类型内存:堆(Heap)和非堆(Permanent区域). 1.Heap是运行时数据区域,所有类实例和数组的内存均从此处分配.Heap区分两大块,一块是 Youn ...
- 从零开始学习jQuery (六) AJAX快餐
一.摘要 本系列文章将带您进入jQuery的精彩世界, 其中有很多作者具体的使用经验和解决方案, 即使你会使用jQuery也能在阅读中发现些许秘籍. 本篇文章讲解如何使用jQuery方便快捷的实现A ...
- Extjs4-treepanel-解析json/fields中是否加入leaf的区别
json解析list时,我原先的写法是: Map<String, Object> map = new HashMap<String, Object>(); map.put(&q ...
- GPIO
一.什么是GPIO? 首先应该理解什么是GPIO.GPIO,英文全称为General-Purpose IO ports,也就是通用IO口.在嵌入式系统中常常有数量众多,但是结构却比较简单的 ...