您的位置:首页 > 编程语言 > Qt开发

QT 动态更改SVG的颜色

2018-03-09 10:06 1301 查看
好久没有写QT了, 前阵子写的控件都没时间整理和改进,一直有个想法就是想将里面的PNG改成SVG,因为png用QPixmap绘制出来的是位图,一放大就失真,之前研究的将PNG颜色更改就白忙活了,代码如下
void GaugeColorScheme::setCenterImageColor(QImage &image,QColor &color)
{
image  = image.convertToFormat(QImage::Format_RGBA8888_Premultiplied,Qt::NoFormatConversion);
int bmpWidth = image.width();
int bmpHeight = image.height();
for(int i=0;i< bmpWidth;++i)
{
for(int j=0;j<bmpHeight;++j)
{
//将灰色(0~255)全部替换成设定的颜色,全透明的不替换
QColor tempColor = image.pixelColor(i,j);
if(tempColor.alpha() != 0)
{
color.setAlpha(tempColor.alpha());
image.setPixelColor(i,j,color);
}
}
}
}

QImage image = centerPixImg.toImage();
setCenterImageColor(image,centerImgColor);

painter->drawImage(-image.width()/2,-image.height()/2, image);
以上代码是将png颜色替换的方法,给需要的朋友,在这里我没有用这种方法了,为了绘制出来的图标不失真,我想到了svg。
svg图标格式其实本质上是一个xml文件,我本想直接使用QT封装的SVG操作类,无耐没有找到好的方法,我想既然是xml文件,那就直接用QT的xml操作类,对文件的相关属性进行更改就可以了,我找了一个svg文件打开并研究里面的内容,在这里我给大家推荐一个图标下载库,也许有很多朋友都知道这个库,那就是“阿里图标库”,里面有大量的免费的图标下载。



以上是我打开一个svg图标的内容,是不是很简单,在根为svg,在里面描述了图标的大小等信息,在有个子标签path,描述了图标的填充颜色以及绘制路径等信息,我们所需要的就是这个填充颜色,我们只要更改它就可以了,所以我设计了以下一个函数。void GaugeStation::SetAttrRecur(QDomElement &elem, QString strtagname, QString strattr, QString strattrval)
{
// if it has the tagname then overwritte desired attribute
if (elem.tagName().compare(strtagname) == 0)
{
elem.setAttribute(strattr, strattrval);
}
// loop all children
for (int i = 0; i < elem.childNodes().count(); i++)
{
if (!elem.childNodes().at(i).isElement())
{
continue;
}
SetAttrRecur(elem.childNodes().at(i).toElement(), strtagname, strattr, strattrval);
}
} elem:DOM树的一个元素句柄   strtagname:标签名  strattr:属性名    strattrval:属性值
由以上函数可以看出,我是用的DOM的方式对svg进行解析和修改的,在函数中我用了一个递归的方式对svg中的数据进行更改。具体大家可以自己去深入研究一下QT对xml的操作方法。接下来大家看我的调用。void GaugeStation::drawCenterPixMap(QPainter *painter)
{
painter->save();
int width_svg = 50;
int height_svg = 50;

QFile file( centerSvgPath );
file.open(QIODevice::ReadOnly);
QByteArray baData = file.readAll();
// load svg contents to xml document and edit contents
QDomDocument doc;
doc.setContent(baData);

file.close();
// recurivelly change color

if(innerCurrValue >= 0)
{
//正角度
SetAttrRecur(doc.documentElement(), "path", "fill", rgb2HexStr(centerPixMapNegativeColor));
}
else
{
//负角度
SetAttrRecur(doc.documentElement(), "path", "fill", rgb2HexStr(centerPixMapPositiveColor));
}

QSvgRenderer m_svgRender(doc.toByteArray());
m_svgRender.render(painter ,QRectF(-width_svg,-height_svg/2,width_svg ,height_svg));
painter->restore();
}在使用这QT操作xml,以及svg时,要加入 QT += xml svg
并包含头文件:#include<QDomDocument> #include<QSvgRenderer> #include<QFile>
我们用QFile将文件打开并获取内容到QDomDocument然后调用函数,更改path标签下的fill属性,更改后将内容导入QSvgRenderer,利用painter将内容绘制出来。
另外在svg中描述颜色好像只能是 :red,blue,black。。。等,以及颜色的16进制字符串格式,所以我写了一个QColor 转16进制字符串的函数,不知道QT中有没有其它好用的方法不用自己转换的,我们方法如下:QString GaugeStation::rgb2HexStr(const QColor &color)
{
QString redStr = QString("%1").arg(color.red(), 2, 16, QChar('0'));
QString greenStr = QString("%1").arg(color.green(), 2, 16, QChar('0'));
QString blueStr = QString("%1").arg(color.blue(), 2, 16, QChar('0'));
QString key = "#" + redStr + greenStr + blueStr;
return key;
}方法介绍完毕,如里大家有更好的方法,可以告诉我,欢迎大家来指正,谢谢!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: