问题
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