簡體   English   中英

在qt中更改svg的顏色

[英]Change the color of an svg in qt

我在資源中加載了一個 svg,但它是黑色的。 如何將顏色更改為白色?

這就是您在 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。

只要您在 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。

希望有幫助。

如果您的 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,但考慮到幾乎所有提供圖標的網站都是黑色的,這非常簡潔。

您可以使用 ColorOverlay,如本問題末尾所述:

Qt QML LevelAdjust 在應用於 svg 源時顯示奇怪的邊緣效果

它不會改變SVG,但它會創建一個與您的繪圖具有相同形狀的彩色圖層(假設您的繪圖背景是透明的)。

如果白色是您唯一需要的顏色,那么一個簡單的解決方案是使用圖像編輯器(例如 Inkscape)更改原始 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;
}

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)

很老的線程,但也如此查看,所以我需要為像我這樣仍在使用 qt5 的人回答,但答案不起作用,因為在 qt5 中 doc.documentElement() 返回一個 const 元素。 您需要進行一些簡單的更改才能使其正常工作:

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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM