【问题标题】:How to show SVG image in PyQT5 from string/xml stream?如何在 PyQT5 中从字符串/xml 流中显示 SVG 图像?
【发布时间】:2019-03-21 02:47:39
【问题描述】:

在 Python3/QT5 应用程序中,我试图显示最初构建为字符串的 SVG 图像。我需要操纵这个 SVG 图像(例如改变它的颜色),所以我的字符串会随着时间而改变。这是一个最小的工作示例:

import sys
from PyQt5.QtWidgets import QApplication
from PyQt5.QtSvg import QSvgWidget

svg_str = """<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="300" height="300" viewBox="0 0 300 300" id="smile" version="1.1">
    <path
        style="fill:#ffaaaa"
        d="M 150,0 A 150,150 0 0 0 0,150 150,150 0 0 0 150,300 150,150 0 0 0 
            300,150 150,150 0 0 0 150,0 Z M 72,65 A 21,29.5 0 0 1 93,94.33 
            21,29.5 0 0 1 72,124 21,29.5 0 0 1 51,94.33 21,29.5 0 0 1 72,65 Z 
            m 156,0 a 21,29.5 0 0 1 21,29.5 21,29.5 0 0 1 -21,29.5 21,29.5 0 0 1 
            -21,-29.5 21,29.5 0 0 1 21,-29.5 z m -158.75,89.5 161.5,0 c 0,44.67 
            -36.125,80.75 -80.75,80.75 -44.67,0 -80.75,-36.125 -80.75,-80.75 z"
    />
</svg>
"""
# ==========================================
with open('smile.svg', 'w') as f:
    f.write(svg_str)
# ==========================================
app = QApplication(sys.argv)
svgWidget = QSvgWidget('smile.svg')
svgWidget.setGeometry(100,100,300,300)
svgWidget.show()
sys.exit(app.exec_())

我的问题是我找不到一种方法来解决需要保存文件以便从字符串本身实例化 QSvgWidget 对象的需要。我不想不加选择地保存文件,也找不到将xml 信息直接加载到QSvgWidget 对象的方法...

我找到了一个最接近我的愿望的解决方案,它看起来像这样:

import sys
from PyQt5.QtWidgets import QApplication
from PyQt5.QtSvg import QSvgWidget, QSvgRenderer
from PyQt5.QtCore import QXmlStreamReader
from PyQt5.QtGui import QPainter

svg_str = """<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="300" height="300" viewBox="0 0 300 300" id="smile" version="1.1">
    <path
        style="fill:#ffaaaa"
        d="M 150,0 A 150,150 0 0 0 0,150 150,150 0 0 0 150,300 150,150 0 0 0 
            300,150 150,150 0 0 0 150,0 Z M 72,65 A 21,29.5 0 0 1 93,94.33 
            21,29.5 0 0 1 72,124 21,29.5 0 0 1 51,94.33 21,29.5 0 0 1 72,65 Z 
            m 156,0 a 21,29.5 0 0 1 21,29.5 21,29.5 0 0 1 -21,29.5 21,29.5 0 0 1 
            -21,-29.5 21,29.5 0 0 1 21,-29.5 z m -158.75,89.5 161.5,0 c 0,44.67 
            -36.125,80.75 -80.75,80.75 -44.67,0 -80.75,-36.125 -80.75,-80.75 z"
    />
</svg>
"""
# ==========================================
class QSvgWidget_from_string(QSvgWidget):
    def __init__(self, strSVG):
        super().__init__()
        self.strSVG = strSVG
    def paintEvent(self, event):
        qp = QPainter()
        qp.begin(self)
        svg_render = QSvgRenderer(QXmlStreamReader(self.strSVG))
        qp.restore()
        svg_render.render(qp)
        qp.end()
# ==========================================
app = QApplication(sys.argv)
svgWidget = QSvgWidget_from_string(svg_str)
svgWidget.setGeometry(100,100,300,300)
svgWidget.show()
sys.exit(app.exec_())

但我不满意,因为我需要扩展 QSvgWidget 类只是为了从 xml 字符串实例化它。我的问题是:有什么方法可以做到这一点而不必求助于QPaintpaintEvent

【问题讨论】:

    标签: python-3.x svg qt5 pyqt5


    【解决方案1】:

    如果您不需要QSvgWidget,例如你想得到QImage(你可以从中得到QPixmapQIcon)你可以使用:

    qimage = QtGui.QImage.fromData(svg_bytes)
    

    确保svg 位于supportedImageFormats

    【讨论】:

      【解决方案2】:

      您可以获得QSvgWidget 使用的QSvgRenderer 来渲染SVG。它允许从文件、字节数组或流中加载数据:

      import sys
      from PyQt5.QtWidgets import QApplication
      from PyQt5.QtSvg import QSvgWidget, QSvgRenderer
      
      svg_str = """<?xml version="1.0" encoding="UTF-8" standalone="no"?>
      <svg width="300" height="300" viewBox="0 0 300 300" id="smile" version="1.1">
          <path
              style="fill:#ffaaaa"
              d="M 150,0 A 150,150 0 0 0 0,150 150,150 0 0 0 150,300 150,150 0 0 0 
                  300,150 150,150 0 0 0 150,0 Z M 72,65 A 21,29.5 0 0 1 93,94.33 
                  21,29.5 0 0 1 72,124 21,29.5 0 0 1 51,94.33 21,29.5 0 0 1 72,65 Z 
                  m 156,0 a 21,29.5 0 0 1 21,29.5 21,29.5 0 0 1 -21,29.5 21,29.5 0 0 1 
                  -21,-29.5 21,29.5 0 0 1 21,-29.5 z m -158.75,89.5 161.5,0 c 0,44.67 
                  -36.125,80.75 -80.75,80.75 -44.67,0 -80.75,-36.125 -80.75,-80.75 z"
          />
      </svg>
      """
      
      svg_bytes = bytearray(svg_str, encoding='utf-8')
      
      app = QApplication(sys.argv)
      svgWidget = QSvgWidget()
      svgWidget.renderer().load(svg_bytes)
      svgWidget.setGeometry(100,100,300,300)
      svgWidget.show()
      sys.exit(app.exec_())
      

      更多信息在这里:http://doc.qt.io/qt-5/qsvgrenderer.html

      【讨论】:

        猜你喜欢
        • 2021-10-09
        • 2018-12-28
        • 2020-11-23
        • 2020-08-09
        • 2020-06-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-13
        相关资源
        最近更新 更多