PedanticHacker asked
Since using
PyQt6
, I am getting this strange error:qt.svg: <input>:1:8277: Could not parse node: radialGradient
The
QSvgRenderer
(used by theQSvgWidget
) can't display radial gradients inPyQt6
. This same code, that I have, worked perfectly fine inPyQt5
, but now onPyQt6
, it does not render radial gradients in SVGs anymore. Is there a workaround or something?
Martin Fitzpatrick
I wonder if there are just some bugs in Qt6 at the moment. Remember the weird glitching effects I saw on the QGraphicsScene
while using SVG in Qt6? Though losing radial gradient support is a bit weird.
Can you share the SVG? Might be worth validating it.
PedanticHacker
Never miss an update
Enjoyed this? Subscribe to get new updates straight in your Inbox.
Well, the code for generating the SVG chessboard is on the python-chess' GitHub site HERE.
The rendering part of the code for the generated python-chess SVG is HERE.
The board()
method of the chess.svg
module is the one that generates the SVG chessboard, based upon the arguments given to that method. For the check mark that is the check
argument. The code given to the check
argument of chess.svg.board()
method is:
if self.board.is_check():
return self.board.king(self.board.turn)
where self.board
is chess.Board()
instance.
The error, when there is check in a chessboard position, is this:
qt.svg: <input>:1:7114: Could not parse node: radialGradient
qt.svg: <input>:1:31331: Could not resolve property: #check_gradient
Martin Fitzpatrick
Below is a small test case example which works in PyQt5 (read on for the solution in PyQt6). Here's the radial gradient (saved to a file named "gradient.svg") and the test program.
The svg
<svg width="400" height="150">
<defs>
<radialGradient id="grad1"><stop offset="0%" stop-color="#ff0000" stop-opacity="1.0" /><stop offset="50%" stop-color="#e70000" stop-opacity="1.0" /><stop offset="100%" stop-color="#9e0000" stop-opacity="0.0" /></radialGradient>
</defs>
<ellipse fill="url(#grad1)" cx="200" cy="70" rx="85" ry="55"/>
<text x="150" y="86" fill="green" font-family="Verdana" font-size="45">SVG</text>
</svg>
The test program
import math
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QGraphicsScene, QGraphicsView
from PyQt5.QtSvg import QGraphicsSvgItem
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.scene = QGraphicsScene()
self.viewer = QGraphicsView()
self.setCentralWidget(self.viewer)
svg = QGraphicsSvgItem('gradient.svg')
self.scene.addItem(svg)
self.viewer.setScene(self.scene)
app = QApplication(sys.argv)
w = MainWindow()
w.show()
app.exec_()
The same code in PyQt6, which just needs to change the import for from PyQt6.QtSvgWidgets import QGraphicsSvgItem
import math
import sys
from PyQt6.QtWidgets import QApplication, QMainWindow, QGraphicsScene, QGraphicsView
from PyQt6.QtSvgWidgets import QGraphicsSvgItem
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.scene = QGraphicsScene()
self.viewer = QGraphicsView()
self.setCentralWidget(self.viewer)
svg = QGraphicsSvgItem('gradient.svg')
self.scene.addItem(svg)
self.viewer.setScene(self.scene)
app = QApplication(sys.argv)
w = MainWindow()
w.show()
app.exec()
Switching out the radial gradient for a linear one, it works, e.g.
<svg width="400" height="150">
<defs>
<linearGradient id="grad1" y1="0%" x1="0%" y2="0%" x2="100%">
<stop offset="0%" style="stop-color:rgb(255,255,0);stop-opacity:1"/>
<stop offset="100%" style="stop-color:rgb(255,0,0);stop-opacity:1"/>
</linearGradient>
</defs>
<ellipse fill="url(#grad1)" cx="200" cy="70" rx="85" ry="55"/>
<text x="150" y="86" fill="green" font-family="Verdana" font-size="45">SVG</text>
</svg>
Looks like the following (in PyQt6)
I looked up some other radial gradients online, and some don't throw the error. Porting back the attributes of the elements that work I found that adding an r (radius) attribute to the radialGradient will mean it doesn't throw the error. The value necessary to give the expected gradient is 0.5
<radialGradient id="grad1" r="0.5">
<stop offset="0%" stop-color="#ff0000" stop-opacity="1.0"/>
<stop offset="50%" stop-color="#e70000" stop-opacity="1.0"/>
<stop offset="100%" stop-color="#9e0000" stop-opacity="0.0"/>
</radialGradient>
It makes some sense, in that a radial gradient doesn't really make sense without a radius.
The result with the above
Final SVG code
<svg width="400" height="150">
<defs>
<radialGradient id="grad1" r="0.5">
<stop offset="0%" stop-color="#ff0000" stop-opacity="1.0"/>
<stop offset="50%" stop-color="#e70000" stop-opacity="1.0"/>
<stop offset="100%" stop-color="#9e0000" stop-opacity="0.0"/>
</radialGradient>
</defs>
<ellipse fill="url(#grad1)" cx="200" cy="70" rx="85" ry="55"/>
<text x="150" y="86" fill="green" font-family="Verdana" font-size="45">SVG</text>
</svg>
PedanticHacker
Wow, Martin, you nailed it! I just needed to pass the r
attribute with the value of 0.5
and now it works perfectly in PyQt6
. Thank you, thank you, thank you, you are truly a master hacker! :+1:
I have reported this "missing r
attribute" bug in python-chess and the issue has already been fixed. However, the python-chess author (Niklas Fiekas) told me that if the r
attribute is missing, it should default to 50%
, as specified HERE, saying If the attribute is not specified, the effect is as if a value of '50%' were specified.
. I don't know what guys at Riverbank changed in PyQt6 to break this. :thinking: