Qt自定义控件----PushButton显示svg矢量图

文章目录

  • 前言
  • 一、实现原理
  • 二、svg图片的内容展示
  • 三、核心代码实现
    • 1.XML修改svg填充色
    • 2.QPushButton中绘制Svg矢量图
  • 总结


前言

QSS中给按钮添加图片,如果按钮的大小与png的大小不一致,造成png图片会出现压缩或者放大,此时png图片会模糊。为了让程序自适应布局、dpi变化或者显示分辨率变化,图标不模糊,考虑使用svg矢量图来代替png图片。效果如下图:


一、实现原理

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图片因为缩放引起的图标模糊问题;使界面更加美观

你可能感兴趣的:(Qt,qt,开发语言)