How to change color of SVG icon
-
I load one of those SVG icons from https://fonts.google.com/icons and try to change the color. I could not find anything in the web which may work.
Here my current code:
from PyQt5.QtWidgets import (QGraphicsItem, QWidget, QStyleOptionGraphicsItem) from PyQt5.QtGui import QPainter from PyQt5.QtSvg import QSvgRenderer from PyQt5.QtCore import QRectF import os class QRFGraphicsNode(QGraphicsItem): def paint(self, painter: QPainter, option: QStyleOptionGraphicsItem, widget: Optional[QWidget] = ...): # region Icon svg = QSvgRenderer() svg.load(f"{os.getcwd()}/src/assets/icons/material/keyboard_FILL0_wght400_GRAD0_opsz48.svg") svg.render(painter, QRectF(220, 5, 48, 48)) # endregion
The SVG itself:
<svg xmlns="http://www.w3.org/2000/svg" height="48" width="48"><path d="M7 38q-1.2 0-2.1-.925Q4 36.15 4 35V13q0-1.2.9-2.1.9-.9 2.1-.9h34q1.2 0 2.1.9.9.9.9 2.1v22q0 1.15-.9 2.075Q42.2 38 41 38Zm0-3h34V13H7v22Zm8-3.25h18v-3H15Zm-4.85-6.25h3v-3h-3Zm6.2 0h3v-3h-3Zm6.15 0h3v-3h-3Zm6.2 0h3v-3h-3Zm6.15 0h3v-3h-3Zm-24.7-6.25h3v-3h-3Zm6.2 0h3v-3h-3Zm6.15 0h3v-3h-3Zm6.2 0h3v-3h-3Zm6.15 0h3v-3h-3ZM7 35V13v22Z"/></svg>
The result:
I would like to change the color of the SVG. I tried to change the pen and the brush from the
painter
but without any effect (painter.setPen(QPen(QColor('#fff')))
andpainter.setBrush(QBrush(QColor('#fff')))
). -
I load one of those SVG icons from https://fonts.google.com/icons and try to change the color. I could not find anything in the web which may work.
Here my current code:
from PyQt5.QtWidgets import (QGraphicsItem, QWidget, QStyleOptionGraphicsItem) from PyQt5.QtGui import QPainter from PyQt5.QtSvg import QSvgRenderer from PyQt5.QtCore import QRectF import os class QRFGraphicsNode(QGraphicsItem): def paint(self, painter: QPainter, option: QStyleOptionGraphicsItem, widget: Optional[QWidget] = ...): # region Icon svg = QSvgRenderer() svg.load(f"{os.getcwd()}/src/assets/icons/material/keyboard_FILL0_wght400_GRAD0_opsz48.svg") svg.render(painter, QRectF(220, 5, 48, 48)) # endregion
The SVG itself:
<svg xmlns="http://www.w3.org/2000/svg" height="48" width="48"><path d="M7 38q-1.2 0-2.1-.925Q4 36.15 4 35V13q0-1.2.9-2.1.9-.9 2.1-.9h34q1.2 0 2.1.9.9.9.9 2.1v22q0 1.15-.9 2.075Q42.2 38 41 38Zm0-3h34V13H7v22Zm8-3.25h18v-3H15Zm-4.85-6.25h3v-3h-3Zm6.2 0h3v-3h-3Zm6.15 0h3v-3h-3Zm6.2 0h3v-3h-3Zm6.15 0h3v-3h-3Zm-24.7-6.25h3v-3h-3Zm6.2 0h3v-3h-3Zm6.15 0h3v-3h-3Zm6.2 0h3v-3h-3Zm6.15 0h3v-3h-3ZM7 35V13v22Z"/></svg>
The result:
I would like to change the color of the SVG. I tried to change the pen and the brush from the
painter
but without any effect (painter.setPen(QPen(QColor('#fff')))
andpainter.setBrush(QBrush(QColor('#fff')))
).It's surprising that no one responded in nine months. I was hoping to hear back sooner.
I found two possible solutions.
A) Pixmap:
from PyQt6.QtGui import QPainter, QFontMetrics, QPainterPath, QPen, QBrush, QStaticText, QFont, QColor, QPixmap from PyQt6.QtCore import Qt, QPointF, QPoint, QRectF from PyQt6.QtSvg import QSvgRenderer import os def drawIconPixmap(painter: QPainter, x, y, icon, size=56, color=Qt.GlobalColor.white): svg = QSvgRenderer() svg.load(os.path.join(os.path.dirname(sys.modules[__name__].__file__), '../assets/icons/material/', icon)) # Create a transparent QPixmap to render the SVG onto pixmap = QPixmap(size, size) pixmap.fill(Qt.GlobalColor.transparent) # Render the SVG onto the pixmap svgPainter = QPainter(pixmap) svg.render(svgPainter, QRectF(0, 0, size, size)) svgPainter.end() # Convert the QPixmap to a QImage image = pixmap.toImage() # Iterate over each pixel of the image for i in range(image.width()): for j in range(image.height()): # Check if the pixel is not transparent if image.pixelColor(i, j).alpha() > 0: # Set the color of non-transparent parts to white image.setPixelColor(i, j, QColor(Qt.GlobalColor.white)) # Create a new QPixmap from the modified QImage modifiedPixmap = QPixmap.fromImage(image) painter.setOpacity(.1) # Draw the final image onto the scene painter.drawPixmap(x, y, modifiedPixmap) painter.setOpacity(1)
B) Manipulating the SVG content
from PyQt6.QtGui import QPainter, QFontMetrics, QPainterPath, QPen, QBrush, QStaticText, QFont, QColor, QPixmap from PyQt6.QtCore import Qt, QPointF, QPoint, QRectF from PyQt6.QtSvg import QSvgRenderer import os from xml.etree import ElementTree as ET def changeSvgFill(svg_path, fill_color): # Parse the SVG content tree = ET.parse(svg_path) root = tree.getroot() # Define the SVG namespace ns = {'svg': 'http://www.w3.org/2000/svg'} # Find the path element path_element = root.find('.//svg:path', ns) if path_element is not None: # If 'fill' attribute exists, update it if 'fill' in path_element.attrib: path_element.attrib['fill'] = f'#{fill_color}' # If 'fill' attribute does not exist, add it else: path_element.set('fill', f'#{fill_color}') # Serialize the modified SVG to bytes modified_svg_bytes = ET.tostring(root, encoding='utf-8') return modified_svg_bytes def drawIcon(painter: QPainter, x, y, icon, size=56, color='111111', opacity=1): svg = QSvgRenderer() svgBytes = PaintHelper.changeSvgFill(os.path.join(os.path.dirname(sys.modules[__name__].__file__), '../assets/icons/material/', icon), color) svg.load(svgBytes) painter.setOpacity(opacity) svg.render(painter, QRectF(x, y, size, size)) painter.setOpacity(1)
-
-
It's surprising that no one responded in nine months. I was hoping to hear back sooner.
I found two possible solutions.
A) Pixmap:
from PyQt6.QtGui import QPainter, QFontMetrics, QPainterPath, QPen, QBrush, QStaticText, QFont, QColor, QPixmap from PyQt6.QtCore import Qt, QPointF, QPoint, QRectF from PyQt6.QtSvg import QSvgRenderer import os def drawIconPixmap(painter: QPainter, x, y, icon, size=56, color=Qt.GlobalColor.white): svg = QSvgRenderer() svg.load(os.path.join(os.path.dirname(sys.modules[__name__].__file__), '../assets/icons/material/', icon)) # Create a transparent QPixmap to render the SVG onto pixmap = QPixmap(size, size) pixmap.fill(Qt.GlobalColor.transparent) # Render the SVG onto the pixmap svgPainter = QPainter(pixmap) svg.render(svgPainter, QRectF(0, 0, size, size)) svgPainter.end() # Convert the QPixmap to a QImage image = pixmap.toImage() # Iterate over each pixel of the image for i in range(image.width()): for j in range(image.height()): # Check if the pixel is not transparent if image.pixelColor(i, j).alpha() > 0: # Set the color of non-transparent parts to white image.setPixelColor(i, j, QColor(Qt.GlobalColor.white)) # Create a new QPixmap from the modified QImage modifiedPixmap = QPixmap.fromImage(image) painter.setOpacity(.1) # Draw the final image onto the scene painter.drawPixmap(x, y, modifiedPixmap) painter.setOpacity(1)
B) Manipulating the SVG content
from PyQt6.QtGui import QPainter, QFontMetrics, QPainterPath, QPen, QBrush, QStaticText, QFont, QColor, QPixmap from PyQt6.QtCore import Qt, QPointF, QPoint, QRectF from PyQt6.QtSvg import QSvgRenderer import os from xml.etree import ElementTree as ET def changeSvgFill(svg_path, fill_color): # Parse the SVG content tree = ET.parse(svg_path) root = tree.getroot() # Define the SVG namespace ns = {'svg': 'http://www.w3.org/2000/svg'} # Find the path element path_element = root.find('.//svg:path', ns) if path_element is not None: # If 'fill' attribute exists, update it if 'fill' in path_element.attrib: path_element.attrib['fill'] = f'#{fill_color}' # If 'fill' attribute does not exist, add it else: path_element.set('fill', f'#{fill_color}') # Serialize the modified SVG to bytes modified_svg_bytes = ET.tostring(root, encoding='utf-8') return modified_svg_bytes def drawIcon(painter: QPainter, x, y, icon, size=56, color='111111', opacity=1): svg = QSvgRenderer() svgBytes = PaintHelper.changeSvgFill(os.path.join(os.path.dirname(sys.modules[__name__].__file__), '../assets/icons/material/', icon), color) svg.load(svgBytes) painter.setOpacity(opacity) svg.render(painter, QRectF(x, y, size, size)) painter.setOpacity(1)
@dschiller Did not see your post before. I use inkscape to change colors of my svg files when needed, not in the code.