2

I am trying to render styled pygal charts using Qt SVG renderer. But I still problems with background colors because it is black. Shouldn't it be controlled by the style of pygal chart? It should look like the first chart in http://www.pygal.org/en/stable/documentation/builtin_styles.html#darkstyle

enter image description here

import sys
import pygal
from PySide import QtGui, QtSvg


class Chart(QtGui.QWidget):

    def __init__(self, parent=None):
        super(Chart, self).__init__(parent)

        chart = pygal.StackedLine(fill=True, interpolate='cubic',
                                  style=pygal.style.DefaultStyle)
                                  # or e.g. DarkSolarizedStyle
        chart.add('A', [1, 3, 5, 16, 13, 3, 7])
        chart.add('B', [5, 2, 3, 2, 5, 7, 17])
        chart.add('C', [6, 10, 9, 7, 3, 1, 0])
        chart.add('D', [2, 3, 5, 9, 12, 9, 5])
        chart.add('E', [7, 4, 2, 1, 2, 10, 0])
        svgSource = chart.render()
        self.renderer = QtSvg.QSvgRenderer()
        self.renderer.load(svgSource)

    def paintEvent(self, event):
        if self.renderer is not None:
            painter = QtGui.QPainter(self)
            self.renderer.render(painter)
            return True
        return super(Chart, self).paintEvent(event)

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    window = Chart()
    window.show()
    result = app.exec_()
    sys.exit(result)

UPDATE: I get the same issue when using PyQt5, PyQt4, Pyside and also when using directly QSvgWidget. My suspicion is that it does not work because of failure in loading CSS files referenced in the SVG. Or it might be some limited scope of SVG specification which is supported by Qt as mentioned in Does QT support svg?.

Community
  • 1
  • 1

1 Answers1

2

OK, I have found the solution. The problem is that QtSvg supports only a portion of the SVG functionality which is required to render SVGs created by pygal. This is mentioned explicitly in Qt docs: "Qt supports the static features of SVG 1.2 Tiny. ECMA scripts and DOM manipulation are currently not supported." I think this is the reason why more complex SVGs are not being able to render using QtSvg. Moreover QtSvg is talked in discussions about as deprecated (though I have not found any official statement regarding this).

My solution is to use QtWebKit (at the moment I need to support Qt4.8 so I am not using more moder QtWebEngine module, which is expected to deprecate QtWebKit in the near future in Qt5.x).

The lines of code to show pygal generated SVG are these:

chart = pygal.StackedLine(...
...
window = QtWebKit.QWebView()
window.setContent(chart.render())
window.show()

UPDATE: Qt is going to deprecate QtWebKit soon. Also the import modules for PySide/PyQt4 and PyQt5 are different. In order to make it work, you need to use some of these QtWebKit.QWebView (PySide, PyQt4), QtWebKitWidgets.QWebView (older PyQt5), QtWebEngine.QWebEngineView (probably PySide2 - have not tested) and QtWebEngineWidgets.QWebEngineView (modern PyQt5). By 'modern' I roughly mean Qt version >= 5.5.

Regarding rendering of pygal charts, QtWebKit does not support all dynamic features, while QtWebEngine does. The drawback of QtWebEngine is much slower startup.