【问题标题】:Get js console.log as python variable in QWebView pyqt在 QWebView pyqt 中获取 js console.log 作为 python 变量
【发布时间】:2017-07-27 15:35:52
【问题描述】:

我正在尝试构建一个应用程序,该应用程序使用 python 创建一些 html + js 代码并将其加载到 QWebView 中。

最终的html + js 代码如下(原始代码可用here):

<head><meta charset="utf-8" /><script src="https://cdn.plot.ly/plotly-latest.min.js"></script></head><div id="myDiv" style="height: 100%; width: 100%;" class="plotly-graph-div"></div><script type="text/javascript">window.PLOTLYENV=window.PLOTLYENV || {};window.PLOTLYENV.BASE_URL="https://plot.ly";Plotly.newPlot("myDiv", [{"type": "scatter", "x": [6.81, 6.78, 6.49, 6.72, 6.88, 7.68, 7.69, 7.38, 6.76, 6.84, 6.91, 6.74, 6.77, 6.73, 6.68, 6.94, 6.72], "y": [1046.67, 1315.0, 1418.0, 997.33, 2972.3, 9700.0, 6726.0, 6002.5, 2096.0, 2470.0, 867.0, 2201.7, 1685.6, 2416.7, 1618.3, 2410.0, 2962.0], "mode": "markers", "ids": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]}], {"showlegend": true}, {"linkText": "Export to plot.ly", "showLink": false})</script>
<script>    
    var plotly_div = document.getElementById('myDiv')
    var plotly_data = plotly_div.data
    plotly_div.on('plotly_selected', function(data){
    featureId = plotly_data[0].ids[data.points[0].pointNumber]
    featureIds = []
    data.points.forEach(function(pt) {
    featureIds.push(parseInt(pt.id))
        })
    console.log(featureIds)
    })
</script>

感谢plotly python API,此代码创建了一个绘图。通过将绘图保存在本地文件中(例如/home/matteo/plot.html),我可以使用以下代码将其加载到 QWebView 中:

from PyQt5.QtWebKit import QWebSettings
from PyQt5.QtWebKitWidgets import *
from PyQt5.QtCore import QUrl
import json

plot_view = QWebView()
plot_view.page().setNetworkAccessManager(QgsNetworkAccessManager.instance())
plot_view_settings = plot_view.settings()
plot_view_settings.setAttribute(QWebSettings.WebGLEnabled, True)
plot_view_settings.setAttribute(QWebSettings.DeveloperExtrasEnabled, True)
plot_view_settings.setAttribute(QWebSettings.Accelerated2dCanvasEnabled, True)

plot_path = '/home/matteo/plot.html'
plot_url = QUrl.fromLocalFile(plot_path)
plot_view.load(plot_url)
plot_view.show()

上面的javascript函数只是在使用绘图的lasso selection工具时在javascript控制台中返回绘图选定点的id。

使用inspect 工具检查,它在 QWebView 中也可以正常工作:每次选择中的元素时,在 console.log 中我可以看到该点的相应 id。

这是取自 jsfiddle 的静态图片(套索选择、点选择和 console.log 输出):

运行代码可用here,只需启用调试控制台并使用套索选择工具选择某个点。

我真正想要实现的是获取控制台的输出(即所选点的 id),然后将它们重新注入应用程序,以获得可用的 python 对象(列表、字典、无论如何)每次我进行选择时。

有没有办法链接QWebPage的javascript控制台来获取python对象?

【问题讨论】:

    标签: javascript python pyqt plotly qwebview


    【解决方案1】:

    要得到console.log()的输出,只需要覆盖方法javaScriptConsoleMessage()

    另外:我添加了两种访问点列表的方式,第一种是通过属性obj,第二种是通过信号。

    class _LoggedPage(QWebPage):
        obj = [] # synchronous
        newData = pyqtSignal(list) #asynchronous
        def javaScriptConsoleMessage(self, msg, line, source):
            l = msg.split(",")
            self.obj = l
            self.newData.emit(l)
            print ('JS: %s line %d: %s' % (source, line, msg))
    

    完整示例:

    class _LoggedPage(QWebPage):
        obj = [] # synchronous
        newData = pyqtSignal(list) #asynchronous
        def javaScriptConsoleMessage(self, msg, line, source):
            l = msg.split(",")
            self.obj = l
            self.newData.emit(l)
            print ('JS: %s line %d: %s' % (source, line, msg))
    
    def onNewData(data):
        print("asynchronous", data)
    
    app = QApplication(sys.argv)
    plot_view = QWebView()
    page = _LoggedPage()
    page.newData.connect(onNewData)
    
    plot_view.setPage(page)
    plot_path = '/home/qhipa/plot.html'
    plot_url = QUrl.fromLocalFile(plot_path)
    plot_view.load(plot_url)
    plot_view_settings = plot_view.settings()
    plot_view_settings.setAttribute(QWebSettings.WebGLEnabled, True)
    plot_view_settings.setAttribute(QWebSettings.DeveloperExtrasEnabled, True)
    plot_view_settings.setAttribute(QWebSettings.Accelerated2dCanvasEnabled, True)
    
    # synchronous request simulation
    timer = QTimer(plot_view)
    timer.timeout.connect(lambda: print("synchronous", page.obj))
    timer.start(1000)
    
    plot_view.show()
    sys.exit(app.exec_())
    

    【讨论】:

    • 非常感谢您的回答。我用了你的代码,它可以工作。但是,我无法将输出 store 存储在一个我可以在稍后使用的变量中。通过在javaScriptConsoleMessage 之前添加obj = [] 来编辑代码,然后尝试返回对象retunr self.obj 我总是得到相同的错误:TypeError: invalid result from _LoggedPage.javaScriptConsoleMessage()。我错过了什么吗?再次感谢!
    • 完美!谢谢!
    猜你喜欢
    • 1970-01-01
    • 2017-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多