I am displaying a folium generated HTML(for leaflet.js) in a QtWebEngineView. In the popups I have a button w/ an on-click function that's supposed to call a method back in python. But I cant seem to get the channel to work. I'm not sure if I'm doing something wrong with the QtWebChannel or the JS, or could it be folium?
I've injected the following javascript to end of QWebChannel.js, which loads at the end of the <body>
var jshelper;
new QWebChannel(qt.webChannelTransport, function (channel) {
jshelper = channel.objects.jshelper;
});
document.getElementById("myBtn").addEventListener("click", function(){
jshelper.pathSelected("Test!")
});
Here's my Python Code
import sys
import os
import branca
from branca.element import *
import folium
from folium import plugins
from PyQt5 import QtWebEngineWidgets, QtCore, QtWidgets, QtWebChannel
from PyQt5.QtWidgets import QMainWindow, QAction, QMenu, QApplication, QWidget, QLineEdit, QLabel, QPushButton, QGridLayout, QDockWidget
class Example(QMainWindow):
def __init__(self):
super().__init__()
self.setObjectName('Main')
QtCore.QMetaObject.connectSlotsByName(self)
self.view = QtWebEngineWidgets.QWebEngineView()
self.view.setObjectName('MapWidget')
self.window = QWidget()
self.window.setObjectName('MainWidget')
self.layout = QGridLayout()
self.window.setLayout(self.layout)
self.layout.addWidget(self.view)
self.setCentralWidget(self.window);
self.channel = QtWebChannel.QWebChannel(self.view.page())
self.view.page().setWebChannel(self.channel)
self.channel.registerObject("jshelper", self)
self.us = folium.Map(location=[36,-108],
zoom_start=5, tiles='StamenWatercolor')
fastestRoute = folium.PolyLine( ((40,-110), (50,-110)),
weight=5,color='blue').add_to(self.us)
f = Figure()
f.html.add_child(Element('<button id="myBtn">Try it</button>'))
f.html.add_child(Element('<p>\n TEST \n</p>'))
link = JavascriptLink('https://rawgit.com/toknowjoyman/qwebch/master/qwebchannel.js')
f.html.add_child(Element(link.render()))
print (f.render())
iframe = branca.element.IFrame(html=f.render(), width=500, height=300)
popup = folium.Popup(iframe, max_width=500)
fastestRoute.add_child(popup)
self.us.save("html/test.html")
self.view.load(QtCore.QUrl().fromLocalFile(
os.path.split(os.path.abspath(__file__))[0]+r'/html/test.html'
))
self.setGeometry(100,100,1200,900)
self.show()
@QtCore.pyqtSlot(str)
def pathSelected(self, lat):
print(lat)
if __name__ == '__main__':
sys.argv.append("--remote-debugging-port=8000")
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
Would really appreciate the help in figuring this out
Let me know if I should post the folium generated html for the popup or for the leaflet.js api
qwebchannel.js
you must put it first, and you are injecting it into the popup and you are registering it in the page()
.
To do this we create a Figure () and in the header we add the qwebchannel.js
principal = Figure()
js = JavascriptLink(QUrl.fromLocalFile(self.htmlPath.absoluteFilePath("qwebchannel.js")).toString())
principal.header.add_child(Element(js.render()))
Note: In the qwebchannel does not make the connection with the button because it does not exist.
for this the popup is passed a new javascript, which will call popup.js, and where I will access jshelper via his parent, the main window.
popup.js
var jshelper = parent.jshelper;
document.getElementById("myBtn").addEventListener("click", function(){
console.log("okay");
jshelper.pathSelected("Test!");
});
.py
f = Figure()
f.html.add_child(Element('<button id="myBtn">Try it</button>'))
f.html.add_child(Element('<p>\n TEST \n</p>'))
link = JavascriptLink(QUrl.fromLocalFile(self.htmlPath.absoluteFilePath("popup.js")).toString())
f.html.add_child(Element(link.render()))
You can find the complete example in the following link.