Display SVG file in Python

吃可爱长大的小学妹 提交于 2021-02-04 21:01:31

问题


I'm creating a Python3 program that generates SVG images with random circles that I need for a personal project. Right now the program works perfectly, but I'd like to fine-tune some parameters to produce the best results possible. My idea is to have a display window that shows the intermediate result and an interactive shell to change some of the values that generate the position of the circles, without having to create thousands of different images and compare them. When I finish I can simply save the result.

And here comes the problem: I don't really know how to achieve this result. I first thought of using Matplotlib, which is usually perfect for these kind of tasks, but it doesn't seem to be able to read SVG files. I also thought of drawing circles directly into a plot, but some of them have to be blurred (Gaussian blur filter in the SVG file), and Matplotlib doesn't seem to be able to blur shapes. Finally I looked for something else able to display either an SVG file or directly the text the program produces to generate the SVG file, but with no luck.

Edit: I just tried CairoSVG to convert the SVG file to PNG. It works, but it doesn't support Gaussian blur, so it's a suboptimal solution. I can accept a solution that involves converting the SVG file to PNG or some other format, but I'd like it to support at least Gaussian blur, otherwise I can simply draw every circle with Matplotlib.

Thanks in advance for the help!


回答1:


Here's a solution with PyQt5 (or PySide2 in my case) and QWebEngineView (there are mentions here or there that explain why QSvgWidget didn't handle filters like blur).

This is just displaying the svg (with its blur), you will probably want to add widgets to make it interactive as you like:

import sys

from PySide2 import QtCore, QtGui, QtWidgets
from PySide2.QtNetwork import QNetworkProxy, QNetworkProxyFactory
from PySide2.QtWebEngineWidgets import QWebEngineView


class DisplaySVG(QtWidgets.QWidget):
    "A simple SVG display."
    def __init__(self, url=None, parent=None):
        super().__init__(parent)
        self.resize(800,600)
        self.verticalLayout = QtWidgets.QVBoxLayout(self)
        self.webview = QWebEngineView(self)
        self.verticalLayout.addWidget(self.webview)

        self.setWindowTitle("Display SVG")
        act = QtWidgets.QAction("Close", self)
        act.setShortcuts([QtGui.QKeySequence(QtCore.Qt.Key_Escape)])
        act.triggered.connect(self.close)
        self.addAction(act)

        svg = '''
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->

<svg
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:cc="http://creativecommons.org/ns#"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   width="210mm"
   height="297mm"
   viewBox="0 0 210 297"
   version="1.1"
   id="svg8"
   inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
   sodipodi:docname="drawing.svg">
  <defs
     id="defs2">
    <filter
       style="color-interpolation-filters:sRGB;"
       inkscape:label="Blur"
       id="filter4530">
      <feGaussianBlur
         stdDeviation="3.48559 2"
         result="fbSourceGraphic"
         id="feGaussianBlur4528" />
      <feColorMatrix
         result="fbSourceGraphicAlpha"
         in="fbSourceGraphic"
         values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
         id="feColorMatrix4532" />
      <feGaussianBlur
         id="feGaussianBlur4534"
         stdDeviation="3.49 2"
         result="blur"
         in="fbSourceGraphic" />
    </filter>
  </defs>
  <sodipodi:namedview
     id="base"
     pagecolor="#ffffff"
     bordercolor="#666666"
     borderopacity="1.0"
     inkscape:pageopacity="0.0"
     inkscape:pageshadow="2"
     inkscape:zoom="0.7"
     inkscape:cx="214.06823"
     inkscape:cy="366.85869"
     inkscape:document-units="mm"
     inkscape:current-layer="layer1"
     showgrid="false"
     inkscape:window-width="1487"
     inkscape:window-height="958"
     inkscape:window-x="58"
     inkscape:window-y="85"
     inkscape:window-maximized="0" />
  <metadata
     id="metadata5">
    <rdf:RDF>
      <cc:Work
         rdf:about="">
        <dc:format>image/svg+xml</dc:format>
        <dc:type
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
        <dc:title></dc:title>
      </cc:Work>
    </rdf:RDF>
  </metadata>
  <g
     inkscape:label="Layer 1"
     inkscape:groupmode="layer"
     id="layer1">
    <circle
       style="opacity:1;fill:#ff5555;fill-opacity:0.57480317;stroke:#2c2cff;stroke-width:1.882;stroke-miterlimit:4;stroke-dasharray:3.764, 1.88199999999999990;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter4530)"
       id="path4518"
       cx="66.523811"
       cy="123.13095"
       r="36.285713" />
  </g>
</svg>
        '''

        self.webview.setHtml(svg)

qt_app = QtWidgets.QApplication(sys.argv)
disp = DisplaySVG()
disp.show()
qt_app.exec_()


来源:https://stackoverflow.com/questions/63139025/display-svg-file-in-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!