05 扩展组件:自定义CheckBox组件

系列文章目录

01 Qt自定义风格控件的基本原则-CSDN博客

02 从QLabel聊起:自定义控件扩展-图片控件-CSDN博客

03 从QLabel聊起:自定义控件扩展-文本控件-CSDN博客

04 自定义Button组件:令人抓狂的QToolButton文本图标居中问题-CSDN博客


目录

系列文章目录

前言

一、从QCheckBox渲染源码说起

1.QCheckBox渲染源码

2.源码简述

二、自定义Button控件的使用场景

1.风格示意图

[三、 实现思路](#三、 实现思路)

1.概述

2.功能接口举例

3.CheckBox渲染部分代码示例

4.注意事项

总结


前言

在篇幅《04 自定义Button组件:令人抓狂的QToolButton文本图标居中问题》中我根据QToolButton源码简单陈述了:为什么我们在业务开发场景中,同时居中按钮文本、图标复杂的原因。 其根本原因就在于Qt源码中已经把文本元素与图标元素的间隙设为固定值4个像素!

很遗憾的是, QCheckBox复选框控件类依旧存在以下让我不舒服的固定风格:

  • 图标与文本间距依旧固定值4个像素
  • 图标、文本对齐方式固定为水平居左、垂直居中

所以, 今天想分享的是自己在自定义CheckBox组件上的思路与方法!

既聊思路,也说代码!我们开始今天的CheckBox扩展控件类的分享!


一、从QCheckBox渲染源码说起

1.QCheckBox渲染源码

以下为Qt源码中关于QCheckBox复选框渲染的部分代码:

cpp 复制代码
uint alignment = visualAlignment(btn->direction, Qt::AlignLeft | Qt::AlignVCenter);

if (!proxy()->styleHint(SH_UnderlineShortcut, btn, widget))
        alignment |= Qt::TextHideMnemonic;
QPixmap pix;
QRect textRect = btn->rect;
if (!btn->icon.isNull()) {
       pix = btn->icon.pixmap(qt_getWindow(widget), btn->iconSize, btn->state & State_Enabled ? QIcon::Normal : QIcon::Disabled);
proxy()->drawItemPixmap(p, btn->rect, alignment, pix);
if (btn->direction == Qt::RightToLeft)
       textRect.setRight(textRect.right() - btn->iconSize.width() - 4);
 else
      textRect.setLeft(textRect.left() + btn->iconSize.width() + 4);
 }
 if (!btn->text.isEmpty())
{
   proxy()->drawItemText(p, textRect, alignment | Qt::TextShowMnemonic,
            btn->palette, btn->state & State_Enabled, btn->text,         
  QPalette::WindowText);
 }

详情见qcommonstyle.cpp中函数:QCommonStyle::drawControl

2.源码简述

从上述源码可以得知:

首先,在第一行源码中固定了图标、文本的对齐方式为 Qt::AlignLeft | Qt::AlignVCenter;

其次,文本矩形区域textRect 显然以图标矩形的右边为基准且偏移4个像素。

二、自定义CheckBox控件的使用场景

1.风格示意图

示意图2-1

三、 实现思路

1.概述

为了沿用QCheckBox的基本功能接口, 我们需要继承QCheckBox类, 然后在paintEvent中实时绘制图标与文本内容, 必要的话还要区分三态效果(包括:checked unchecked partialChecked)

2.功能接口举例

cpp 复制代码
    //设置对齐方式
    void setAlignment(Qt::Alignment align);
    //图标、文本间距
    void setSpacing(int spacing);
    //设置文本字号
    void setButtonTextSize(int pixSize);
    //设置三态图标
    void setButtonIcon(const QString& checked, const QString& unchecked, const QString& partiallyChecked);
    //设置按钮文本颜色
    void setButtonTextColor(const QColor& clr);

3.CheckBox渲染部分代码示例

cpp 复制代码
    QStylePainter paint(this);
    //背景透明
    paint.fillRect(rect(), Qt::transparent);
    //渲染图标+文本要素 
    QRect rcDisplay = styledRect();
    QRect rcPix = rcDisplay;
    QRect rcText = rcDisplay;
    rcPix.setWidth(iconSize().width());//左上角不变,缩小宽度
    rcText.adjust(rcPix.width() + m_iSpacing, 0, 0, 0);//
    //绘制图标
    QPixmap pix = styledIcon().pixmap(qt_getWindow(this), rcDisplay.size().boundedTo(iconSize()));
    paint.drawItemPixmap(rcPix, Qt::AlignCenter, pix);
    //绘制文本
    paint.setFont(font());
    paint.setPen(styledTextColor());
    paint.drawText(rcText, Qt::AlignCenter, text());

4.注意事项

这里有一点要提醒大伙儿注意, 如果我们通过自绘制改变了文本、图标渲染的位置, 那么CheckBox的点击事件也相应要做处理!(比如:我们的图标绘制在左上角,用户点击右下角是不是应该不响应该次操作呢?)

好在, QCheckBox也给我们预留了虚函数:QCheckBox::hitButton。

必要时,要重写这个虚函数的!


总结

OK,以上就是今天想和大家分享的内容,本篇主要针对QCheckBox类做些功能扩展,然后独立出一个自定义的组件CheckBox。

既聊思路,也说代码!我们下次继续分享自定义风格扩展组件!

PS:本专栏所有篇幅涉及的UI扩展组件类,后面会封装成插件动态库,感兴趣的同学可以留言哦

相关推荐
程序员爱钓鱼3 小时前
【无标题】Go语言中的反射机制 — 元编程技巧与注意事项
开发语言·qt
无畏烧风4 小时前
[Qt] visual studio code 安装 Qt插件
qt
坏柠9 小时前
C++ Qt 基础教程:信号与槽机制详解及 QPushButton 实战
c++·qt
雨落倾城夏未凉10 小时前
4.信号与槽
后端·qt
追风赶月、1 天前
【QT】事件(鼠标、按键、定时器、窗口)
qt
牵牛老人1 天前
Qt处理USB摄像头开发说明与QtMultimedia与V4L2融合应用
stm32·单片机·qt
-凌凌漆-1 天前
【Qt】QStringLiteral 介绍
开发语言·qt
想要入门的程序猿1 天前
Qt写入excel
数据库·qt·excel
丁劲犇1 天前
用 Turbo Vision 2 为 Qt 6 控制台应用创建 TUI 字符 MainFrame
开发语言·c++·qt·tui·字符界面·curse
charlie1145141911 天前
深入理解Qt的SetWindowsFlags函数
开发语言·c++·qt·原理分析