我在资源中加载了一个 svg,但它是黑色的。如何将颜色更改为白色?
8 回答
这就是你在 Qt 中的做法,不要忘记将 xml 和 svg 模块添加到你的 qt 项目(*.pro 文件)中。此代码片段通过修改任何“路径”元素的“填充”属性来更改颜色,但您可以使用它来修改任何元素的任何属性。
void SetAttrRecur(QDomElement &elem, QString strtagname, QString strattr, QString strattrval);
void ChangeSVGColor()
{
// open svg resource load contents to qbytearray
QFile file("myfile.svg");
file.open(QIODevice::ReadOnly);
QByteArray baData = file.readAll();
// load svg contents to xml document and edit contents
QDomDocument doc;
doc.setContent(baData);
// recurivelly change color
SetAttrRecur(doc.documentElement(), "path", "fill", "white");
// create svg renderer with edited contents
QSvgRenderer svgRenderer(doc.toByteArray());
// create pixmap target (could be a QImage)
QPixmap pix(svgRenderer.defaultSize());
pix.fill(Qt::transparent);
// create painter to act over pixmap
QPainter pixPainter(&pix);
// use renderer to render over painter which paints on pixmap
svgRenderer.render(&pixPainter);
QIcon myicon(pix);
// Use icon ....
}
void 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);
}
}
由于 SVG 格式是基于 XML 的,而 XML 只是 ASCII 文本……您可以将 SVG 资源加载到 QString 中,调用 QString::replace("\"#000000\"", "\"#ffffff\" "),然后将修改后的 QString 传递给您的 QSVGRenderer。
如果你的 SVG 是黑色的,有一个非常简单的方法可以做到:QGraphicsEffect
#include <QGraphicsItem>
#include <QGraphicsColorizeEffect>
QGraphicsItem *item;
QGraphicsColorizeEffect *effect;
item = new QGraphicsItem;
effect = new QGraphicsColorizeEffect;
effect->setColor(Qt::white);
effect->setStrength(1);
item->setGraphicsEffect(effect)
这不适用于白色 SVG,但考虑到几乎所有提供图标的网站都是黑色的,这非常简洁。
只要您在 Mac 上不需要它,这应该可以工作:
http://doc-snapshot.qt-project.org/4.8/qwidget.html#setGraphicsEffect
http://doc-snapshot.qt-project.org/4.8/qgraphicscolorizeeffect.html
编辑:或者如果您需要支持 Mac,请在 QGraphicsView 中进行 svg 渲染和效果。
http://doc-snapshot.qt-project.org/4.8/qgraphicsitem.html#setGraphicsEffect
设置您的着色效果将其着色为白色,并将其设置为 svgWidget。
希望有帮助。
pyqt5 的解决方案。您可以轻松地将其转换为 c++
def QIcon_from_svg(svg_filepath, color='black'):
img = QPixmap(svg_filepath)
qp = QPainter(img)
qp.setCompositionMode(QPainter.CompositionMode_SourceIn)
qp.fillRect( img.rect(), QColor(color) )
qp.end()
return QIcon(img)
您可以使用 ColorOverlay,如本问题末尾所述:
Qt QML LevelAdjust 在应用于 svg 源时显示奇怪的边缘效果
它不会更改 SVG,但它会创建一个彩色图层,该图层的形状与您的绘图相同(假设您的绘图背景是透明的)。
#ifndef SVG_ITEM_H
#define SVG_ITEM_H
#include <QObject>
#include <QPen>
#include <QQuickItem>
#include <QQuickPaintedItem>
#include <QSvgRenderer>
class SVG_Item : public QQuickPaintedItem
{
Q_PROPERTY(QString source READ source WRITE setSource NOTIFY sourceChanged)
Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
Q_PROPERTY(QPen stroke READ stroke WRITE setStroke NOTIFY strokeChanged)
Q_PROPERTY(bool debuging READ debuging WRITE setdebuging)
Q_PROPERTY(QColor backgroundColor READ backgroundColor WRITE setBackgroundColor NOTIFY backgroundColorChanged)
Q_OBJECT
public:
explicit SVG_Item(QQuickItem *parent = nullptr);
void paint(QPainter *painter) Q_DECL_OVERRIDE;
QString source() const;
QColor color() const;
QPen stroke() const;
bool debuging() const;
QColor backgroundColor() const;
signals:
void sourceChanged(QString source);
void colorChanged(QColor color);
void strokeChanged(QPen stroke);
void backgroundColorChanged(QColor backgroundColor);
public slots:
void setSource(QString source);
void setColor(QColor color);
void setStroke(QPen stroke);
void setdebuging(bool debuging);
void setBackgroundColor(QColor backgroundColor);
private:
QString m_source;
QColor m_color;
QPen m_stroke;
QString svgContent;
QSvgRenderer *renderer;
bool changed;
bool m_debuging;
QColor m_backgroundColor;
QColor m_test;
};
#endif // SVG_ITEM_H
#include "svg_item.h"
#include <QSvgRenderer>
#include <QDebug>
#include <QPainter>
#include <QSvgGenerator>
SVG_Item::SVG_Item(QQuickItem *parent) : QQuickPaintedItem(parent)
{
changed = false;
renderer = NULL;
m_debuging = false;
m_backgroundColor = Qt::transparent;
}
void SVG_Item::paint(QPainter *painter)
{
painter->fillRect(0,0,this->width(),this->height(),m_backgroundColor);
if(m_source != "")
{
if(changed)
{
if(renderer != NULL)
{
renderer->deleteLater();
}
renderer = new QSvgRenderer(svgContent.toLocal8Bit());
}
if(renderer != NULL)
renderer->render(painter);
}
}
void SVG_Item::setSource(QString source)
{
if(source.startsWith("qrc"))
source = source.remove(0,3);
if (m_source == source)
return;
QFile readFile(source);
if(!readFile.exists())
{
qWarning("file not found");
}
readFile.open(QFile::ReadOnly);
svgContent = readFile.readAll();
setColor(color());
//readData.replace()
m_source = source;
emit sourceChanged(m_source);
}
void SVG_Item::setColor(QColor color)
{
changed = true;
QString fillStr = "fill:%1";
fillStr = fillStr.arg(color.name());
svgContent = svgContent.replace(QRegExp("fill:[# 0-9 a b c d e f A B C D E F]+"), fillStr);
if(!svgContent.contains(QRegExp("fill:[# 0-9 a b c d e f A B C D E F]+")))
{
QString style = "<path \n style=\"fill:%1;fill-opacity:1\"";
style = style.arg(color.name());
svgContent = svgContent.replace("<path",style);
style = "<rect \n style=\"fill:%1;fill-opacity:1\"";
style = style.arg(color.name());
svgContent = svgContent.replace("<rect",style);
style = "<circle \n style=\"fill:%1;fill-opacity:1\"";
style = style.arg(color.name());
svgContent = svgContent.replace("<circle",style);
style = "<ellipse \n style=\"fill:%1;fill-opacity:1\"";
style = style.arg(color.name());
svgContent = svgContent.replace("<ellipse",style);
style = "<polygon \n style=\"fill:%1;fill-opacity:1\"";
style = style.arg(color.name());
svgContent = svgContent.replace("<polygon",style);
}
//
this->update();
if (m_color == color)
return;
m_color = color;
emit colorChanged(m_color);
}
void SVG_Item::setStroke(QPen stroke)
{
changed = true;
if (m_stroke == stroke)
return;
m_stroke = stroke;
emit strokeChanged(m_stroke);
}
void SVG_Item::setdebuging(bool debuging)
{
m_debuging = debuging;
}
void SVG_Item::setBackgroundColor(QColor backgroundColor)
{
if (m_backgroundColor == backgroundColor)
return;
m_backgroundColor = backgroundColor;
emit backgroundColorChanged(m_backgroundColor);
}
QString SVG_Item::source() const
{
return m_source;
}
QColor SVG_Item::color() const
{
return m_color;
}
QPen SVG_Item::stroke() const
{
return m_stroke;
}
bool SVG_Item::debuging() const
{
return m_debuging;
}
QColor SVG_Item::backgroundColor() const
{
return m_backgroundColor;
}
如果白色是您需要的唯一颜色,那么一个简单的解决方案是使用图像编辑器(例如 Inkscape)更改原始 SVG 图像的颜色。当然,如果您需要使用多种不同颜色的图像,那将不是一个合理的解决方案。