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: "(" ... ...
随机推荐
- HDU3368+枚举
题意看不懂的直接看百度百科对黑白棋的解释... 做法:分情况讨论,一共8个方向. /* 搜索 */ #include<stdio.h> #include<string.h> ; ...
- c++学习之旅-Cygwin+Eclipse ide for c++
一,cygwin下载完毕后配置系统环境片两path指向cygwin/bin 二,eclipse设置 2.1 设置工作目录的cygwin映射 cygwin/d ->d:\ 2.2设置编译 下面新建 ...
- easyui源码翻译1.32--panel(面板)
前言 昨天发布了表格datagrid的翻译源码 ,easyui的许多插件有依赖关系 比如datagrid 的渲染需要panel.resizable.linkbutton.pagination 今 ...
- Android RelativeLayout
RelativeLayout为相对布局,这种布局内的组件总是相对兄弟组件.父容器来确定的,在定义控件的位置时,需要参照其他控件的位置. 这个程序实现了一个梅花的相对布局 <?xml versio ...
- [译]GotW #3: Using the Standard Library (or, Temporaries Revisited)
高效的代码重用是良好的软件工程中重要的一部分.为了演示如何更好地通过使用标准库算法而不是手工编写,我们再次考虑先前的问题.演示通过简单利用标准库中已有的算法来避免的一些问题. Problem JG Q ...
- 【原创】FPGA开发手记(一) UART接口
以下内容均以Xilinx的Nexys3作为开发板 1. UART简介 UART(即Universal Asynchronous Receiver Transmitter 通用异步收发器)是广泛使用的串 ...
- tlplayer for ios V1.1.1加密测试版本
2014-06-22 修正稳定性. 大家还是可以从原来的下载地址下载. 此为tlplayer for ios版本,可以播放加密视频与非加密视频. 加密视频下载地址:http://blog.csdn.n ...
- 在Sublime Text 3中配置编译和运行Java程序
设置Java的PATH环境变量 在Java的jdk的bin目录下建立新文件runJava.bat 文件内容如下: @echo off cd %~dp1 echo Compiling %~nx1.... ...
- 如何计算IP地址及CIDR,子网掩码计算
如何计算IP地址及CIDR 一. IP地址概念 IP地址是一个32位的二进制数,它由网络ID和主机ID两部份组成,用来在网络中唯一的标识的一台计算机.网络ID用来标识计算机所处的网段:主 机ID用来标 ...
- BZOJ1334: [Baltic2008]Elect
1334: [Baltic2008]Elect Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 386 Solved: 201[Submit][Sta ...