我在资源中加载了一个svg,但是它是黑色的。我如何将颜色更改为白色?
23c0lvtd1#
这是你在Qt中可以做到的,别忘了把xml和svg模块添加到你的qt项目(*.pro文件)中。这个代码片段通过修改任何“path”元素的“fill”属性来改变颜色,但是你可以用它来修改任何元素的任何属性。
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); } }
neskvpey2#
由于SVG格式是基于XML的,而XML只是ASCII文本...您可以将SVG资源加载到QString中,调用QString::replace(“"#000000"",“"#ffffff"”),然后将修改后的QString传递到您的QSVGRenderer。
hl0ma9xz3#
如果您的SVG是黑色的,有一个非常简单的方法可以做到这一点:Q图形效果
#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,但考虑到几乎所有提供黑色图标的网站,这是相当整洁的。
f5emj3cl4#
可以很容易地将其转换为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)
42fyovps5#
只要你不需要它在Mac上,这应该工作:http://doc-snapshot.qt-project.org/4.8/qwidget.html#setGraphicsEffecthttp://doc-snapshot.qt-project.org/4.8/qgraphicscolorizeeffect.html编辑:或者如果你需要支持Mac,在QGraphicsView中做svg渲染和效果。http://doc-snapshot.qt-project.org/4.8/qgraphicsitem.html#setGraphicsEffect设置colorize效果为白色,并将其设置为svgWidget。希望能有所帮助。
vsikbqxv6#
您可以使用ColorOverlay,如本问题结尾所述:Qt QML LevelAdjust shows strange edge effects when applied to svg source它不会改变SVG本身,但是它创建了一个彩色层,该层将具有与您的绘图相同的形状(假设您的绘图的背景是透明的)。
svujldwt7#
#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; }
hmae6n7t8#
很老的线程,但也是如此看待,所以我需要回答那些像我一样仍然在使用qt5,答案是不工作的,因为在qt5的doc.documentElement()返回一个常量元素。有一些简单的改变,你需要使它工作:
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; } QDomElement docElem = elem.childNodes().at(i).toElement(); //<-- make const "variable" SetAttrRecur(docElem, strtagname, strattr, strattrval); } } QIcon ChangeSVGColor(QString iconPath, QString color) { // open svg resource load contents to qbytearray QFile file(iconPath); if(!file.open(QIODevice::ReadOnly)) return {}; QByteArray baData = file.readAll(); // load svg contents to xml document and edit contents QDomDocument doc; doc.setContent(baData); // recurivelly change color QDomElement docElem = doc.documentElement(); //<-- make const "variable" SetAttrRecur(docElem, "path", "fill", color); // 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); return myicon; }
gblwokeq9#
如果白色是你唯一需要的颜色,那么一个简单的解决方案就是用图像编辑器(例如Inkscape)改变原始SVG图像的颜色。当然,如果你需要使用许多不同颜色的图像,那就不是一个合理的解决方案了。
9条答案
按热度按时间23c0lvtd1#
这是你在Qt中可以做到的,别忘了把xml和svg模块添加到你的qt项目(*.pro文件)中。这个代码片段通过修改任何“path”元素的“fill”属性来改变颜色,但是你可以用它来修改任何元素的任何属性。
neskvpey2#
由于SVG格式是基于XML的,而XML只是ASCII文本...您可以将SVG资源加载到QString中,调用QString::replace(“"#000000"",“"#ffffff"”),然后将修改后的QString传递到您的QSVGRenderer。
hl0ma9xz3#
如果您的SVG是黑色的,有一个非常简单的方法可以做到这一点:Q图形效果
这不适用于白色SVG,但考虑到几乎所有提供黑色图标的网站,这是相当整洁的。
f5emj3cl4#
可以很容易地将其转换为c++
42fyovps5#
只要你不需要它在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
设置colorize效果为白色,并将其设置为svgWidget。
希望能有所帮助。
vsikbqxv6#
您可以使用ColorOverlay,如本问题结尾所述:
Qt QML LevelAdjust shows strange edge effects when applied to svg source
它不会改变SVG本身,但是它创建了一个彩色层,该层将具有与您的绘图相同的形状(假设您的绘图的背景是透明的)。
svujldwt7#
hmae6n7t8#
很老的线程,但也是如此看待,所以我需要回答那些像我一样仍然在使用qt5,答案是不工作的,因为在qt5的doc.documentElement()返回一个常量元素。有一些简单的改变,你需要使它工作:
gblwokeq9#
如果白色是你唯一需要的颜色,那么一个简单的解决方案就是用图像编辑器(例如Inkscape)改变原始SVG图像的颜色。当然,如果你需要使用许多不同颜色的图像,那就不是一个合理的解决方案了。