前言
QSS中给按钮添加图片,如果按钮的大小与png的大小不一致,造成png图片会出现压缩或者放大,此时png图片会模糊。为了让程序自适应布局、dpi变化或者显示分辨率变化,图标不模糊,考虑使用svg矢量图来代替png图片。效果如下图:一、实现原理
<font color=#999AAA
svg矢量图内部使用的时xml文件进行描述。文件中有很多元素和其对应的属性值。本文主要对单色图标的填充色进行修改,达到使用一张svg图片通过修改填充色,完成按钮的 normal、disable、hover、pressed、checked五个状态的属性切换。
二、svg图片的内容展示
单色Svg图标,通过修改元素“path” 的"fill"属性的值,来修改填充色<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg t="1644473700072" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2758" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128">
<defs>
<style type="text/css"></style>
</defs>
<path d="M640 456h-118.4V320a32 32 0 0 0-64 0v136H320a32 32 0 0 0 0 64h137.6V640a32 32 0 1 0 64 0v-120H640a32 32 0 1 0 0-64z" p-id="2759" fill="#d81e06"></path>
<path d="M919.264 905.984l-138.912-138.912C851.808 692.32 896 591.328 896 480c0-229.376-186.624-416-416-416S64 250.624 64 480s186.624 416 416 416c95.008 0 182.432-32.384 252.544-86.208l141.44 141.44a31.904 31.904 0 0 0 45.248 0 32 32 0 0 0 0.032-45.248zM128 480C128 285.92 285.92 128 480 128s352 157.92 352 352-157.92 352-352 352S128 674.08 128 480z" p-id="2760" fill="#d81e06"></path></svg>
三、核心代码实现
1.XML修改svg填充色
xml中修改元素 属性的代码如下void XmlFile::setEleAttributeValueP(QDomElement &elem, const QString& strtagname, const QString& strattr, const QString& strattrval)
{
if (elem.tagName().compare(strtagname) == 0)
{
QString before_color = elem.attribute(strattr);
elem.setAttribute(strattr, strattrval);
QString color = elem.attribute(strattr);
}
for (int i = 0; i < elem.childNodes().count(); i++)
{
if (!elem.childNodes().at(i).isElement())
{
continue;
}
QDomElement ele = elem.childNodes().at(i).toElement();
setEleAttributeValueP(ele, strtagname, strattr, strattrval);
}
}
2.QPushButton中绘制Svg矢量图
绘制核心代码如图void CusSvgPushButton::paintSvgBtn(QPainter* painter, const QStyleOptionButton& btnOption, QStyle* style) const
{
QStyleOptionButton tmp = btnOption;
//优先绘制底层按钮
//QStylePainter p(wid);
tmp.text = "";
//tmp.state &= ~(QStyle::State_Raised | QStyle::State_Sunken | QStyle::State_AutoRaise);
style->drawControl(QStyle::CE_PushButton, &tmp,painter,this); //先绘制底层
this->changeSvgFillColor(btnOption);
//绘制svg图标
QSvgRenderer m_svgRender;
m_svgRender.load(dPtr->mSvgFile.toByteArray());
if (dPtr->mIsBorderImage)
{
m_svgRender.render(painter, btnOption.rect);
qDebug() << "btnOption rect = " << btnOption.rect;
}
else
{
QRect txtRect;
QRect svgRect;
this->calSvgBtnTxtRect(btnOption,svgRect, txtRect);
painter->drawText(txtRect, Qt::AlignCenter, btnOption.text);
m_svgRender.render(painter, svgRect);
}
}
void CusSvgPushButton::changeSvgFillColor(const QStyleOptionButton& option) const
{
//根据绘制状态的变换来修改填充色
//qDebug() << "option state " << option.state;
int tmpDrawState = Draw_State_None;
//如果是checkd,则为check状态
if (option.state & QStyle::State_On)
tmpDrawState = Draw_State_Checked;
else if (option.state & QStyle::State_Sunken)
tmpDrawState = Draw_State_Pressed;
else if (option.state & QStyle::State_MouseOver)
tmpDrawState = Draw_State_Hover;
else if (option.state & QStyle::State_Enabled)
tmpDrawState = Draw_State_Enable;
else
tmpDrawState = Draw_State_Disabled;
if (tmpDrawState == dPtr->mDrawState)
return;
dPtr->mDrawState = (StyleDrawState)tmpDrawState;
switch (tmpDrawState)
{
case Draw_State_Hover:
{
if(dPtr->mSvgHoverColor.isValid())
dPtr->mSvgFile.setEleAttributeValue("path", "fill", dPtr->mSvgHoverColor.name());
break;
}
case Draw_State_Checked:
{
if (dPtr->mSvgCheckedColor.isValid())
dPtr->mSvgFile.setEleAttributeValue("path", "fill", dPtr->mSvgCheckedColor.name());
break;
}
case Draw_State_Pressed:
{
if (dPtr->mSvgPressColor.isValid())
dPtr->mSvgFile.setEleAttributeValue("path", "fill", dPtr->mSvgPressColor.name());
break;
}
case Draw_State_Enable:
{
if (dPtr->mSvgNormalColor.isValid())
dPtr->mSvgFile.setEleAttributeValue("path", "fill", dPtr->mSvgNormalColor.name());
break;
}
case Draw_State_Disabled:
{
if (dPtr->mSvgDisableColor.isValid())
dPtr->mSvgFile.setEleAttributeValue("path", "fill", dPtr->mSvgDisableColor.name());
break;
}
default:
break;
}
}
总结
使用svg矢量图能解决 png图片因为缩放引起的图标模糊问题;使界面更加美观