美化QTabWidget

1.效果展示

2.用法展示

MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);setupUI();ui->tabWidget->addTab2(new QWidget(), tr("this is first tab"));
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::setupUI()
{connect(ui->tabWidget, SIGNAL(TabInserted(int)), this, SLOT(OnTabInserted(int)));connect(ui->tabWidget, SIGNAL(AddBtnClicked()), this, SLOT(OnAddBtnClicked()));connect(ui->tabWidget, SIGNAL(TabClosed(int)), this, SLOT(OnCloseTab(int)));
}void MainWindow::OnTabInserted(int index)
{QPushButton *button = new QPushButton();button->setFixedSize(this->iconSize());button->setStyleSheet("border-image: url(:/images/x-capture-options.png);");ui->tabWidget->setTabButton2(index, QTabBar::LeftSide, button);button = new QPushButton();button->setStyleSheet("QPushButton{border-image: url(:/images/close.png)}""QPushButton:hover{border-image: url(:/images/close_hover.png)}");ui->tabWidget->setTabButton2(index, QTabBar::RightSide, button);
}void MainWindow::OnTabClosed(int index)
{//todo something
}void MainWindow::OnAddBtnClicked()
{ui->tabWidget->addTab2(new QWidget(), tr("this is first tab"));
}

3.原理简介

主要原理就是对paintEvent重写,以及QProxyStyle继承重新实现。我也是翻了很多资料,看了实现的源码才知道的。

  • QExtTabBarStyle继承自QProxyStyle
void QExtTabBarStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *option, QPainter *painter,const QWidget *widget) const
{if (pe == QStyle::PE_IndicatorArrowLeft) {drawArrow(pe, option, painter, widget);} else if (pe == QStyle::PE_IndicatorArrowRight) {drawArrow(pe, option, painter, widget);} else{QProxyStyle::drawPrimitive(pe, option, painter, widget);}
}int QExtTabBarStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const
{if (PM_TabBarScrollButtonWidth == metric) {return 30;} else {return QProxyStyle::pixelMetric(metric, option, widget);}
}QRect QExtTabBarStyle::subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const
{if (SE_TabBarTabLeftButton == element) {return calcIconRect(true, option);} else if (SE_TabBarTabRightButton == element) {return calcIconRect(false, option);} else {return QProxyStyle::subElementRect(element, option, widget);}
}QRect QExtTabBarStyle::calcIconRect(bool left, const QStyleOption *option) const
{const QStyleOptionTab *tab_option = qstyleoption_cast<const QStyleOptionTab *>(option);QSize icon_size = tab_option->iconSize;const QRect tab_rect = tab_option->rect;QPoint center_pos;QRect button_rect;const int icon_padding = 8;if (left) {center_pos = QPoint(icon_padding+icon_size.width()/2+tab_rect.x(), tab_rect.y()+(tab_rect.height()-icon_size.height())/2+icon_size.height()/2);} else {center_pos = QPoint(tab_rect.x()+tab_rect.width()-icon_padding-icon_size.width()/2, tab_rect.y()+(tab_rect.height()-icon_size.height())/2+icon_size.height()/2);}button_rect = QRect(QPoint(0, 0), icon_size);button_rect.moveCenter(center_pos);return button_rect;
}void QExtTabBarStyle::drawArrow(PrimitiveElement pe, const QStyleOption *option, QPainter *painter,const QWidget *widget) const
{const QToolButton *tool_btn = static_cast<const QToolButton *>(widget);if (nullptr != tool_btn && !tool_btn->isVisible()) return;painter->save();const QStyleOptionTab *tab_option = qstyleoption_cast<const QStyleOptionTab *>(option);QBrush rect_brush;if (!tool_btn->isEnabled()) {rect_brush = Qt::transparent;} else if (tool_btn->underMouse()) {rect_brush = QColor(214, 214, 214);} else {rect_brush = Qt::transparent;}QRect draw_rect = QRect(0, 0, 16, 16);draw_rect.moveCenter(option->rect.center());RoundShadowHelper round_helper;round_helper.FillRoundShadow(painter, option->rect,rect_brush.color(), 4);painter->restore();QProxyStyle::drawPrimitive(pe, option, painter, widget);
}
  • QTabBar中的paintEvent重写
void QtExtTabBar::paintEvent(QPaintEvent *event)
{QPainter painter(this);drawTab(&painter);if (tab_add_button_.draw_plus_btn_)drawPlusBtn(&painter);
}void QtExtTabBar::drawTab(QPainter *painter)
{RoundShadowHelper helper(6,4);int border = helper.GetShadowWidth()/2.0;painter->save();int tab_count = tab_add_button_.draw_plus_btn_ ? count()-1 : count();QStyleOptionTabV3 option;for (int index = 0; index < tab_count; index++) {QRect rect = tabRect(index);initStyleOption(&option, index);// draw background QRect draw_rect = QRect(QPoint(rect.x()+border, rect.y() + border), QSize(rect.width()-border*2, rect.height()-border*2));drawTabBg(painter, helper, option, draw_rect, rect);drawTabText(painter, draw_rect, option);}painter->restore();
}void QtExtTabBar::drawTabText(QPainter *painter, const QRect &draw_rect, const QStyleOptionTabV3 &option)
{// draw textQColor text_color = tb_text_color_.Normal_;QRect text_rect = draw_rect.marginsAdded(margins_);if (QStyle::State_Selected & option.state) {text_color = tb_text_color_.Selected_;} else if (QStyle::State_MouseOver & option.state) {text_color = tb_text_color_.Hover_;}painter->setPen(text_color);QString text = fontMetrics().elidedText(option.text, Qt::ElideRight, text_rect.width(), 0); painter->drawText(text_rect, Qt::AlignLeft | Qt::AlignVCenter, text);
}void QtExtTabBar::drawTabBg(QPainter *painter, RoundShadowHelper &helper, const QStyleOptionTabV3 &option, QRect draw_rect, QRect real_rect)
{painter->setPen(Qt::NoPen);if(QStyle::State_Selected & option.state) {helper.RoundShadow(painter, real_rect);helper.FillRoundShadow(painter, draw_rect, tb_bg_color_.Selected_, helper.GetRadius());} else if(QStyle::State_MouseOver & option.state) {helper.FillRoundShadow(painter, draw_rect, tb_bg_color_.Hover_, helper.GetRadius());}
}void QtExtTabBar::drawPlusBtn(QPainter *painter)
{painter->save();int last_index = count()-1;QStyleOptionTabV3 option;initStyleOption(&option, last_index);QRect draw_rect = QRect(QPoint(0, 0), tab_add_button_.tab_add_btn_size_);draw_rect.moveCenter(tabRect(last_index).center());DrawCircle::Draw(painter, draw_rect, tab_btn_add_color_);DrawCharacter::DrawPlus(painter, draw_rect);painter->restore();
}

4.属性设置

  • 可以自定义tab中的左右button。

  • 可以自定义tab中文字的颜色。

  • 可以设置是否需要绘制“+”按钮。

其他的都可以在代码中找到

5.todo list

  • 不支持tab拖拽
  • 不支持tab, tab button 贴图。

关注微信公众号,获取源码。

美化QTabWidget相关推荐

  1. QT界面美化之QTabWidget

    先上效果图:               主界面效果图 展示动图 一.利用QProxyStyle改变tabBar位置并改变文字方向: 继承QProxyStyle自定义类CustomTabStyle  ...

  2. Qt美化之基础控件美化

    目标:只使用CSS的方式,展示每种控件的可美化内容和细节. 文中使用的CSS样式都是通过如下代码的方式加载到窗口中,文件以UTF-8进行存储. QDir::setCurrent(QApplicatio ...

  3. qt 串口助手 界面美化

    一.最终预览 二.添加资源文件 添加样式表css 三.初始化.引入样式表 ui->setupUi(this);//初始化样式表 this->initStyle();/*** @brief ...

  4. 高仿富途牛牛-组件化(三)-界面美化

    文章目录 一.概述 二.效果展示 三.工具箱 1.布局 a.标题栏 b.客户区 2.功能详解 四.组件模板工具栏 五.其他界面美化 六.使用qss文件 七.相关文章 一.概述 今天是组件化的第三篇文章 ...

  5. Qt QSS界面美化

    一.功能介绍 1.根据刘典武大佬和网上查询的资料,进行更改 https://gitee.com/feiyangqingyun/QWidgetDemo#https://gitee.com/feiyang ...

  6. 6、Qt QSS界面美化

    一.功能介绍 1.根据刘典武大佬和网上查询的资料,进行更改 https://gitee.com/feiyangqingyun/QWidgetDemo#https://gitee.com/feiyang ...

  7. html5搜索框美化,CSS美化的漂亮搜索框

    CSS美化的漂亮搜索框 我要搜索 搜索 var $ = function(id){return document.getElementById(id);} var formSubmit = funct ...

  8. Python Qt GUI设计:QTabWidget、QStackedWidget和QDockWidget容器控件类(提升篇—2)

    目录 1.QTabWidget容器控件类 2.QStackedWidget容器控件类 3.QDockWidget容器控件类 有时候我们可能会面临这样一种情况:所开发的程序包含了太多的控件,导致一个窗口 ...

  9. CentOS 7.7 x86-64安装系统字体及美化实录

    我在rMBP上用VMware Fushion 15.1安装了CentOS 7.7的虚拟机,带有gnome界面,打算用于日常的开发工作.但是发现界面实在是太丑陋了,决定趁周末折腾一下,网上研究了一些资料 ...

最新文章

  1. 安装Exchange2013,FMS服务无法达到启动状态
  2. “指标预警”新功能上线,智能实现数据监测
  3. 《高性能JavaScript》第四章 算法和流程控制
  4. 腾讯专有云研发过程首次披露
  5. nginx设置http强制跳转https
  6. java关闭按钮代码_Java高手看看如何实现关闭按钮
  7. json爬虫获取列表数据不全,已解决
  8. H3C DHCP实验
  9. windows驱动开发 DDK/WDK/WDM/WDF区别
  10. 蔡学镛:编译、反编译、反反编译(转)
  11. Android多开检测的另一个思路
  12. windows cmd 批处理将文件名改为大写:https://blog.csdn.net/llq108/article/details/47185279
  13. diskgenius克隆硬盘无法启动_用Diskgenius克隆分区到另一个磁盘上
  14. 【Python】通过 Python 设置电脑代理端口
  15. Gym 100015H Hidden Code
  16. python ADF单位根检验,序列平稳性检验
  17. 前端基础_像素的处理
  18. 为期两年的研究揭示了Android的大问题
  19. 计算机实验室教师岗位职责,实验室实验教师岗位职责
  20. laravel5 timestamp

热门文章

  1. 爱普生5700T对比当贝X3哪个更值得选,当贝X3智慧功能多更值得看
  2. HTML5期末大作业:静态购物网站设计——静态购物网站模板11页(前台+后台) HTML+CSS+JS
  3. 基于启扬i.MX6UL的免疫荧光分析仪解决方案
  4. 企业宣传产品推广PPT模板
  5. 仿掘金社区全栈项目开发(一)-搭建开发环境
  6. GDUT 寒假排位赛三
  7. mapgis java二次开发_MapGIS开发平台二次开发.docx
  8. 80后不会有马云,马化腾,李彦宏这样的领军人物?
  9. 【证明】实对称矩阵特征向量正交
  10. 数学加强 第一节 第二课