0

I have a problem with PyQt/its Webview. The code that is bothering me should render a chart, but it doesn't. I am using the Highcharts framework and provide the data for the javascript function that renders the chart via Python. I also check whether the webview is ready because that was a previous error of mine. The code in question looks something like this:

command = ('loadPinch(' + str(random.sample(range(10000), 1000)) +
            ', ' + str(['2009', '01', '01']) + ');')
self.webview.page().mainFrame().evaluateJavaScript("""
        var readyStateCheckInterval = setInterval(function() {
            if(document.readyState === 'complete'){ """ +
                command + """
                clearInterval(readyStateCheckInterval);
            }
        }, 10);""")

loadPinch is a JavaScript function and looks similar to this(which in turn looks similar to a Highcharts example graph):

    function loadPinch(data, date){
    $('#container').highcharts({
        chart: {
            zoomType: 'x',
            spacingRight: 20
        },
        title: {text: 'Twitter Trends'},
        subtitle: {
            text: document.ontouchstart === undefined ?
                'Click and drag in the plot area to zoom in' :
                'Pinch the chart to zoom in'
        },
        xAxis: {
            type: 'datetime',
            maxZoom: 10 * 24 * 3600000,
            title: {text: null}
        },
        yAxis: {
            title: {text: 'Occurence'}
        },
        tooltip: {shared: true},
        legend: {enabled: false},
        plotOptions: {
            area: {
                fillColor: {
                    linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1},
                    stops: [
                        [0, Highcharts.getOptions().colors[0]],
                        [1, Highcharts.Color(Highcharts.getOptions().colors[0]).setOpacity(0).get('rgba')]
                    ]
                },
                lineWidth: 1,
                marker: {enabled: false},
                shadow: false,
                states: {hover: {lineWidth: 1}},
                threshold: null
            }
        },
        series: [{
            type: 'area',
            name: 'Twitter Trend',
            pointInterval: 24 * 3600 * 1000,
            pointStart: Date.UTC(date[0], date[1], date[2]),
            data: data
        }]
    });
};

I might tell you that if I print the command that I am handing evaluateJavaScript to the console instead of executing it and pasting it over to the developer console, it gets executed as expected and renders the chart which leads me to believe that there is some sort of race condition I can't track down.

Does someone have an idea of what could be the problem?

Regards, Carson

NOTE: The problem is still relevant.

hellerve
  • 508
  • 1
  • 6
  • 30
  • Do you have any errors in JavaScript console? Could you post **generated** code in browser by your python code? – Paweł Fus May 13 '14 at 12:27
  • There are no errors. The variable readyStateCheckInterval exists, though. The generated code looks similar to this(although the data part is longer): http://pastebin.com/yZ9H6zfD – hellerve May 15 '14 at 15:23
  • Then it looks like evaluateJavaScript doesn't work as you expect. Unfortunatetly I'm not any kind of expert with webView, however, have you tried [this](http://stackoverflow.com/questions/19788294/how-does-evaluatejavascript-work) solutions? – Paweł Fus May 16 '14 at 13:29
  • That is a different evaluateJavascript function sadly(mine is qt, not android). i will be reading a bit info from the docs. – hellerve May 20 '14 at 10:44
  • Does it work properly, when you try simple `console.log('nothing')` in `evaluateJavascript `? – Paweł Fus May 20 '14 at 10:47
  • I already use it in different places where it works as expected and alerts and logs work. o will check back whether they work there as well but i have a feeling that i tested this already. ;) – hellerve May 20 '14 at 11:12
  • Could you add that snippet? See: `function loadPinch(data, date){ console.log('dataType:', typeof data, 'dateType:', typeof date); }` - maybe arguments are strings. – Paweł Fus May 20 '14 at 12:56
  • 1
    after a few tries i managed to solve the problem pretty easily. qt has a loadFinished signal which i just bound to my plot-method. now it works like a charm. Seems like before the site is loaded completely, you cannot add to the JavaScript. – hellerve May 27 '14 at 16:59
  • Add this as answer, to inform another users :) – Paweł Fus May 28 '14 at 13:16

1 Answers1

5

I eventually found my fix; i thought too much in JS terms.

There is a signal in QT that is emitted when the page is finished loading, called loadFinished(). By binding this signal to a slot of mine which executed the call to evaluateJavascript(command), the chart loaded. It seems like Qts webview has problems to execute Javascript when the page hasn't finished loading yet.

Anyway, this is how the code looks like(simplified):

class something():
    def __init__(self):
        self.webview = QtWebkitWidgets.QWebView()
        self._myBindingFunction()

    def _myBindingFunction(self):
        self.webview.loadFinished.connect(self._plot)

    def _plot(self):
        command = ('loadPinch(' + str(random.sample(range(10000), 1000)) +
                   ', ' + str(['2009', '01', '01']) + ');')
        self.webview.page().mainFrame().evaluateJavaScript(command)

Note how that simplifies the JS code; i do not have to check for the site having loaded, because after the signal is emitted, it has to be ready.

Big shoutout to Pawel Fus though for leading me onto the right track. I was already giving it up.

Community
  • 1
  • 1
hellerve
  • 508
  • 1
  • 6
  • 30