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扩展组件类,后面会封装成插件动态库,感兴趣的同学可以留言哦

相关推荐
追风赶月、17 小时前
【QT】使用QSS进行界面美化
开发语言·qt
EutoCool20 小时前
Qt窗口:QToolBar、QStatusBar、QDockWidget、QDialog
开发语言·数据库·c++·嵌入式硬件·qt·前端框架
惺忪979821 小时前
qt 正则表达式
开发语言·qt
枫叶丹41 天前
【Qt开发】Qt的背景介绍(一)
开发语言·qt
new_zhou1 天前
QT5使用cmakelists引入Qt5Xlsx库并使用
开发语言·qt·qxlsx
笨笨马甲1 天前
Qt 3D模块加载复杂模型
开发语言·qt·3d
赟赟、嵌入式1 天前
imx6ul Qt运行qml报错This plugin does not support createPlatformOpenGLContext!
开发语言·qt
EutoCool1 天前
Qt窗口:菜单栏
开发语言·c++·嵌入式硬件·qt·前端框架
云空2 天前
《QtPy:Python与Qt的完美桥梁》
开发语言·python·qt·pyqt
墨月白2 天前
【QT】多线程相关教程
数据库·qt