最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

python - Return value from javascript to pyqt5 - Stack Overflow

programmeradmin6浏览0评论

I'm trying to load and query a JS map widget from inside a PyQt5 application. I'm able to use the method:

PyQt5.QtWebEngineWidgets.QWebEngineView().page().runJavaScript()

to execute JS function from the webpage loaded in a QWebEngineView() but I'm having troubles in understanding how to store back to python a value which is returned by a JS function.

A plete example is available here:

The following PyQt5 code load an html page (pyqtwebtest.html) with a leaflet.js map widget inside a PyQt4 mainwindow and add a button to execute a JS code with the aim to store the returned value inside a python variable ...

#!/usr/local/bin/python36
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtWebEngineWidgets import *


class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.form_widget = FormWidget(self)
        _widget = QWidget()
        _layout = QVBoxLayout(_widget)
        _layout.addWidget(self.form_widget)
        self.setCentralWidget(_widget)


class FormWidget(QWidget):
    def __init__(self, parent):
        super(FormWidget, self).__init__(parent)
        self.__controls()
        self.__layout()

    def __controls(self):
        self.browser = QWebEngineView()
        self.browser.load(QUrl('file:///Users/epi/pyqtwebtest.html'))

    def __layout(self):
        self.vbox = QVBoxLayout()
        self.hBox = QVBoxLayout()
        self.getboundsbutton = QPushButton()
        self.hBox.addWidget(self.browser)
        self.hBox.addWidget(self.getboundsbutton)
        self.vbox.addLayout(self.hBox)
        self.setLayout(self.vbox)

        self.getboundsbutton.clicked.connect(self.getBounds)

    def getBounds(self):
        self.bounds = self.browser.page().runJavaScript("[map.getBounds().getSouthWest().lat, map.getBounds().getSouthWest().lng, map.getBounds().getNorthEast().lat, map.getBounds().getNorthEast().lng]")
        print(self.bounds)
        # this is where I get stuck .. the result is None
        # the same js code in the html file prints the bounds values
        # that I want to store on the python side of the app


def main():
    app = QApplication(sys.argv)
    win = MainWindow()
    win.show()
    app.exec_()


if __name__ == '__main__':
    sys.exit(main())

which load the following html page:

<!DOCTYPE html>
<html>
<head>
    <title>PyQtLeaflet</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="shortcut icon" type="image/x-icon" href="docs/images/favicon.ico" />
    <link rel="stylesheet" href="/[email protected]/dist/leaflet.css" />
    <script src="/[email protected]/dist/leaflet.js"></script>
    <style>
        #map {
            width: 600px;
            height: 400px;
        }
    </style>
</head>
<body>
<div id='map'></div>
<script>
    var mbAttr = 'Map data &copy; <a href="">OpenStreetMap</a> contributors, ' +
            '<a href=".0/">CC-BY-SA</a>, ' +
            'Imagery © <a href="">Mapbox</a>',
        mbUrl = '/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpandmbXliNDBjZWd2M2x6bDk3c2ZtOTkifQ._QA7i5Mpkd_m30IGElHziw';

    var grayscale   = L.tileLayer(mbUrl, {id: 'mapbox.light', attribution: mbAttr}),
        streets  = L.tileLayer(mbUrl, {id: 'mapbox.streets',   attribution: mbAttr});

    var map = L.map('map', {
        center: [10, 10],
        zoom: 10,
        layers: [grayscale]
    });

    var baseLayers = {
        "Grayscale": grayscale,
        "Streets": streets
    };
    L.control.layers(baseLayers).addTo(map);

    // this is the "bounds" variable which I am trying to get from pyqt
    bounds = [map.getBounds().getSouthWest().lat, map.getBounds().getSouthWest().lng, map.getBounds().getNorthEast().lat, map.getBounds().getNorthEast().lng] 
    console.log(bounds)
</script>
</body>
</html>

I understand that this question may be considered a duplicate but I had difficulties in finding the exact same methods for a recent version of pyqt5 (>=5.7)

I'm trying to load and query a JS map widget from inside a PyQt5 application. I'm able to use the method:

PyQt5.QtWebEngineWidgets.QWebEngineView().page().runJavaScript()

to execute JS function from the webpage loaded in a QWebEngineView() but I'm having troubles in understanding how to store back to python a value which is returned by a JS function.

A plete example is available here:

The following PyQt5 code load an html page (pyqtwebtest.html) with a leaflet.js map widget inside a PyQt4 mainwindow and add a button to execute a JS code with the aim to store the returned value inside a python variable ...

#!/usr/local/bin/python36
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtWebEngineWidgets import *


class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.form_widget = FormWidget(self)
        _widget = QWidget()
        _layout = QVBoxLayout(_widget)
        _layout.addWidget(self.form_widget)
        self.setCentralWidget(_widget)


class FormWidget(QWidget):
    def __init__(self, parent):
        super(FormWidget, self).__init__(parent)
        self.__controls()
        self.__layout()

    def __controls(self):
        self.browser = QWebEngineView()
        self.browser.load(QUrl('file:///Users/epi/pyqtwebtest.html'))

    def __layout(self):
        self.vbox = QVBoxLayout()
        self.hBox = QVBoxLayout()
        self.getboundsbutton = QPushButton()
        self.hBox.addWidget(self.browser)
        self.hBox.addWidget(self.getboundsbutton)
        self.vbox.addLayout(self.hBox)
        self.setLayout(self.vbox)

        self.getboundsbutton.clicked.connect(self.getBounds)

    def getBounds(self):
        self.bounds = self.browser.page().runJavaScript("[map.getBounds().getSouthWest().lat, map.getBounds().getSouthWest().lng, map.getBounds().getNorthEast().lat, map.getBounds().getNorthEast().lng]")
        print(self.bounds)
        # this is where I get stuck .. the result is None
        # the same js code in the html file prints the bounds values
        # that I want to store on the python side of the app


def main():
    app = QApplication(sys.argv)
    win = MainWindow()
    win.show()
    app.exec_()


if __name__ == '__main__':
    sys.exit(main())

which load the following html page:

<!DOCTYPE html>
<html>
<head>
    <title>PyQtLeaflet</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="shortcut icon" type="image/x-icon" href="docs/images/favicon.ico" />
    <link rel="stylesheet" href="https://unpkg./[email protected]/dist/leaflet.css" />
    <script src="https://unpkg./[email protected]/dist/leaflet.js"></script>
    <style>
        #map {
            width: 600px;
            height: 400px;
        }
    </style>
</head>
<body>
<div id='map'></div>
<script>
    var mbAttr = 'Map data &copy; <a href="http://openstreetmap">OpenStreetMap</a> contributors, ' +
            '<a href="http://creativemons/licenses/by-sa/2.0/">CC-BY-SA</a>, ' +
            'Imagery © <a href="http://mapbox.">Mapbox</a>',
        mbUrl = 'https://api.tiles.mapbox./v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpandmbXliNDBjZWd2M2x6bDk3c2ZtOTkifQ._QA7i5Mpkd_m30IGElHziw';

    var grayscale   = L.tileLayer(mbUrl, {id: 'mapbox.light', attribution: mbAttr}),
        streets  = L.tileLayer(mbUrl, {id: 'mapbox.streets',   attribution: mbAttr});

    var map = L.map('map', {
        center: [10, 10],
        zoom: 10,
        layers: [grayscale]
    });

    var baseLayers = {
        "Grayscale": grayscale,
        "Streets": streets
    };
    L.control.layers(baseLayers).addTo(map);

    // this is the "bounds" variable which I am trying to get from pyqt
    bounds = [map.getBounds().getSouthWest().lat, map.getBounds().getSouthWest().lng, map.getBounds().getNorthEast().lat, map.getBounds().getNorthEast().lng] 
    console.log(bounds)
</script>
</body>
</html>

I understand that this question may be considered a duplicate but I had difficulties in finding the exact same methods for a recent version of pyqt5 (>=5.7)

Share edited May 23, 2017 at 12:03 CommunityBot 11 silver badge asked Jan 21, 2017 at 14:19 epifanioepifanio 1,3671 gold badge17 silver badges28 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 7

runJavaScript in QtWebEngine works asynchronously, so it never returns a value - instead, you pass a callback (i.e. a Python function) to it which gets called with the javascript value. For your example, you could simply pass print as second argument.

发布评论

评论列表(0)

  1. 暂无评论