在PyQt中使用evaluateJavaScript - 函数未被调用

0 投票
1 回答
2274 浏览
提问于 2025-04-18 00:53

我在使用PyQt和它的Webview时遇到了一个问题。让我烦恼的代码应该是用来绘制一个图表的,但它没有成功。我正在使用Highcharts这个框架,并通过Python提供数据给一个用JavaScript写的函数来渲染图表。我还检查了Webview是否准备好了,因为之前我就是因为这个出错。相关的代码大概是这样的:

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是一个JavaScript函数,看起来和这个很像(而这个又和Highcharts的示例图表很相似):

    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
        }]
    });
};

我可以告诉你,如果我把要交给evaluateJavaScript的命令打印到控制台,而不是直接执行它并粘贴到开发者控制台,它就会按预期执行并渲染出图表。这让我觉得可能存在某种我无法追踪的竞争条件。

有没有人知道可能是什么问题呢?

祝好,
Carson

注意:这个问题仍然存在。

1 个回答

5

我最终找到了问题的解决办法;我之前想得太像JavaScript了。

在QT中,有一个信号叫做 loadFinished(),它会在页面加载完成时发出。通过把这个信号绑定到我的一个槽(也就是一个处理函数),然后在这个槽里调用 evaluateJavascript(command),图表就能正常加载了。看起来QT的webview在页面还没加载完成时,执行JavaScript会有问题。

总之,这段代码看起来是这样的(简化版):

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)

注意,这样做简化了JavaScript的代码;我不需要检查网站是否加载完成,因为信号发出后,页面肯定已经准备好了。

特别感谢 Pawel Fus,是他让我找到了正确的方向。我差点就放弃了。

撰写回答