Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt for Python
  4. How to change color of SVG icon
Forum Updated to NodeBB v4.3 + New Features

How to change color of SVG icon

Scheduled Pinned Locked Moved Solved Qt for Python
3 Posts 2 Posters 2.4k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • D Offline
    D Offline
    dschiller
    wrote on last edited by dschiller
    #1

    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:

    d01b883a-c419-4aa0-8da9-c6920d8118c4-Screenshot 2023-02-03 at 23.00.51.png

    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'))) and painter.setBrush(QBrush(QColor('#fff'))) ).

    D 1 Reply Last reply
    0
    • D dschiller

      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:

      d01b883a-c419-4aa0-8da9-c6920d8118c4-Screenshot 2023-02-03 at 23.00.51.png

      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'))) and painter.setBrush(QBrush(QColor('#fff'))) ).

      D Offline
      D Offline
      dschiller
      wrote on last edited by dschiller
      #2

      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)
      
      JoeCFDJ 1 Reply Last reply
      0
      • D dschiller has marked this topic as solved on
      • D dschiller

        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)
        
        JoeCFDJ Offline
        JoeCFDJ Offline
        JoeCFD
        wrote on last edited by JoeCFD
        #3

        @dschiller Did not see your post before. I use inkscape to change colors of my svg files when needed, not in the code.

        1 Reply Last reply
        0

        • Login

        • Login or register to search.
        • First post
          Last post
        0
        • Categories
        • Recent
        • Tags
        • Popular
        • Users
        • Groups
        • Search
        • Get Qt Extensions
        • Unsolved