代码之家  ›  专栏  ›  技术社区  ›  iperetta

如何从string/xml流在PyQT5中显示SVG图像?

  •  1
  • iperetta  · 技术社区  · 7 年前

    在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格式 字符串。我的问题是: QPaint 和 paintEvent ?

    1 回复  |  直到 7 年前
        1
  •  5
  •   Isma    7 年前

    你可以得到 QSvgRenderer 用于 QSvgWidget 渲染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

        2
  •  3
  •   user898678    7 年前

    QSvgWidget e、 你想得到 QImage (你可以从中 QPixmap QIcon )您可以使用:

    qimage = QtGui.QImage.fromData(svg_bytes)
    

    确保 svg 在 supportedImageFormats .