系列文章目录
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复选框渲染的部分代码:
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.风格示意图
三、 实现思路
1.概述
为了沿用QCheckBox的基本功能接口, 我们需要继承QCheckBox类, 然后在paintEvent中实时绘制图标与文本内容, 必要的话还要区分三态效果(包括:checked unchecked partialChecked)
2.功能接口举例
//设置对齐方式
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渲染部分代码示例
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扩展组件类,后面会封装成插件动态库,感兴趣的同学可以留言哦