系列文章目录
前言
如果让我选一个极其鸡肋的Qt原生控件,我一定会投票给QLabel类!
首先,就其功能而言,我觉得QLabel类的功能相对冗杂!对于QLabel的定位是既可以用于展示文本,也可以用于展示图片。
然而,对于展示文本的场合,却不支持长文本省略模式(就是单行文字过长时,显示...)
对于展示图片的场合, 却又不支持svg格式图片的展示!我们知道如果用QLabel展示png图片,那么任意放缩的场景下,必然会出现图片模糊的情形!所以,我也推荐大伙如果可以的话,最好使用svg格式的资源文件!
另外,如果大伙儿了解qml模块就会知道,它的基本组件并不是Label组件,反而是有两个名为Image和Text的组件, 我认为这两个组件的存在何尝不是对QLabel组件的功能拆解与扩展呢?
所以, 本篇介绍的是QWidget自定义扩展组件-Image组件
一、使用场景
场景很简单,就是单纯用于展示一张静态图的场合, 比如:头像、Logo
![图1-1](https://i-blog.csdnimg.cn/blog_migrate/11ae8a61439c697c16a1cace6818d259.png)
二、实现思路
1. 概述
继承基类QWidget, 在paintEvent中根据填充模式绘制目标图片
2.功能接口
代码如下(示例):
enum FillMode
{
Stretch = 0, //忽略宽高比,水平、垂直方向上拉伸效果=》拉伸铺满
PreserveAspectFit,//保持宽高比铺满效果
PreserveAspectCrop,//保持宽高比裁切铺满效果
Tile, //水平、垂直方向层叠效果
TileVertically,//水平方向铺满、垂直方向层叠效果
TileHorizontally,//垂直方向铺满、水平方向层叠效果
Pad //不添加任何变换,居中显示
};
//设置图片资源路径:支持svg格式及其他png等基本格式
//暂不支持异步加载网络资源
void setSource(const QString& src);
//设置图片填充模式
void setFillMode(FillMode mode);
//图片圆角弧度
void setImageRadius(int radius);
3. 绘制代码示例
void renderSvgPixmap(QPainter* painter)
{
QRect rcFrame = contentsRect();
QSvgRenderer svgRender(m_imgSrc);
if (!svgRender.isValid())
{
qDebug() << "invalid svg image!";
return;
}
QSize sz = svgRender.defaultSize();
double dFrameRatio = rcFrame.width()*1.0 / qMax(1, rcFrame.height());
double dImgRatio = sz.width()*1.0 / qMax(1, sz.height());
//接近为0, 不绘制内容
if (qAbs(dImgRatio) <= 0.001 || qAbs(dFrameRatio) <= 0.001)
return;
QRect rcRender = rcFrame;
switch (m_eFillMode)
{
case QUiImage::Stretch:
svgRender.render(painter, rcRender);
break;
case QUiImage::PreserveAspectFit:
{
if (dFrameRatio > dImgRatio)//基于高度计算宽度
{
int iCanvaW = rcFrame.height()* dImgRatio;
int iCanvaH = rcFrame.height();
rcRender = QRect( (rcFrame.width() - iCanvaW)*0.5
, (rcFrame.height() - iCanvaH)*0.5
, iCanvaW
, iCanvaH);
}
else//基于宽度计算高度
{
int iCanvaW = rcFrame.width();
int iCanvaH = rcFrame.width()/ dImgRatio;
rcRender = QRect((rcFrame.width() - iCanvaW)*0.5
, (rcFrame.height() - iCanvaH)*0.5
, iCanvaW
, iCanvaH);
}
svgRender.render(painter, rcRender);
}
break;
这里有几个细节,可以强调一下,大伙儿不要再次踩坑了:
- 绘制区域我们用QWidget::contentsRect接口, 这样的话不会影响QWidget的margin属性展示
- 因为涉及到svg图片的展示,所以要用到svg模块。 值得一说的是,千万不要把svg资源绘制到一张QPixmap上,然后把QPixmap放缩、绘制到QWidget上!因为这样放缩QPixmap并展示依旧会模糊!
三、总结
以上就是今天要讲的内容,本文主要为针对QLabel图片功能接口的拆分与扩展,然后独立出一个自定义的组件功能类Image。
既聊思路,也说代码!我们下次继续分享自定义风格扩展组件!