QT 动态更改SVG的颜色
2018-03-09 10:06
1301 查看
好久没有写QT了, 前阵子写的控件都没时间整理和改进,一直有个想法就是想将里面的PNG改成SVG,因为png用QPixmap绘制出来的是位图,一放大就失真,之前研究的将PNG颜色更改就白忙活了,代码如下
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;
}方法介绍完毕,如里大家有更好的方法,可以告诉我,欢迎大家来指正,谢谢!
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;
}方法介绍完毕,如里大家有更好的方法,可以告诉我,欢迎大家来指正,谢谢!
相关文章推荐
- 如何动态更改VC控件字体颜色
- QT中设置字体和更改字体颜色
- android中为TextView动态改变字体颜色,如点击时更改
- android 动态改变SVG的颜色
- Qt更改icon颜色
- 答静静:动态更改水晶报表部分数据的背景颜色(VB.Net)
- JavaScript 动态更改sharepoint 列表的颜色
- 答静静:动态更改水晶报表部分数据的背景颜色(VB.Net)
- svg中动态更改text属性值
- 答静静:动态更改水晶报表部分数据的背景颜色(VB.Net)
- Delphi中如何动态更改DBGrid的颜色
- wince 静态文本框字体和颜色、背景色的动态更改
- Qt制作的动态颜色渐变表盘
- 代码动态改变SVG矢量图颜色
- Android button 圆角动态更改背景颜色
- 在带(继承)TextView的控件中,在代码中动态更改TextView的文字颜色
- QT中设置字体和更改字体颜色
- 如何动态更改VC控件字体颜色
- 通过代码动态更改progressbar的颜色
- 用Qt Designer 给对话框控件添加背景图片和颜色或者插入图片