Я пытаюсь перенести этот код: https://gist.github.com/ataffanel/13aac4b79bc0080b881f на самые последние версии pyqt5, таким образом, используя qtwebengine. Цель состоит в том, чтобы в конце концов получить виджет карты.
Это код, который у меня уже есть, работающий со случайным html и javascript, он работал, но я не могу получить представление карты, для которого предназначен исходный код.
Основной.ру:
class MainWindow(QtWidgets.QWidget):
def __init__(self):
super(MainWindow, self).__init__()
self.setupUi()
self.show()
self.raise_()
def setupUi(self):
#self.setFixedSize(800, 500)
vbox = QtWidgets.QVBoxLayout()
self.setLayout(vbox)
label = self.label = QtWidgets.QLabel()
sp = QtWidgets.QSizePolicy()
sp.setVerticalStretch(0)
label.setSizePolicy(sp)
vbox.addWidget(label)
view = self.view = QtWebEngineWidgets.QWebEngineView()
channel = self.channel = QWebChannel()
channel.registerObject('MainWindow', self)
view.page().setWebChannel(channel)
# view.page().mainFrame().addToJavaScriptWindowObject("MainWindow", self)
# view.page().setLinkDelegationPolicy(QQWebPage.DelegateAllLinks)
html = open('src/main/assets/map.html','r').read()
self.view.setHtml(html)
view.loadFinished.connect(self.onLoadFinished)
#view.linkClicked.connect(QtWidgets.QDesktopServices.openUrl)
vbox.addWidget(view)
button = QtWidgets.QPushButton('Go to Paris')
panToParis = functools.partial(self.panMap, 2.3272, 48.8620)
button.clicked.connect(panToParis)
vbox.addWidget(button)
def onLoadFinished(self, ok):
if ok:
page=self.view.page()
with open('src/main/assets/map.js', 'r') as f:
src=f.read()
page.runJavaScript(src)
@QtCore.pyqtSlot(float, float)
def onMapMove(self, lat, lng):
self.label.setText('Lng: {:.5f}, Lat: {:.5f}'.format(lng, lat))
def panMap(self, lng, lat):
page=self.view.page()
page.runJavaScript('map.panTo(L.latLng({}, {}));'.format(lat, lng))
if __name__ == '__main__':
app = QtWidgets.QApplication([])
w = MainWindow()
app.exec_()
карта.html:
<!DOCTYPE html>
<html>
<head>
<script src = "qrc:///qtwebchannel/qwebchannel.js"></script>
<link rel = "stylesheet" href = "http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css" />
<script src = "http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script>
<style>
body { padding: 0; margin: 0; }
html, body, #map { height: 100%; }
</style>
</head>
<body>
<div id = "map"></div>
</body>
</html>
карта.js:
var map = L.map('map').setView([55.61121, 12.99351], 16);
L.tileLayer('http://otile{s}.mqcdn.com/tiles/1.0.0/map/{z}/{x}/{y}.png', {
maxZoom: 18,
attribution: 'Map data © <a href = "http://openstreetmap.org">OpenStreetMap</a> contributors, ' +
'tiles Courtesy of <a href = "http://www.mapquest.com/" target = "_blank">MapQuest</a>',
subdomains: '1234',
}).addTo(map);
var marker = L.marker(map.getCenter()).addTo(map);
marker.bindPopup("Hello World!").openPopup();
new QWebChannel(qt.webChannelTransport, function (channel) {
window.MainWindow = channel.objects.MainWindow;
if (typeof MainWindow != 'undefined') {
var onMapMove = function() { MainWindow.onMapMove(map.getCenter().lat, map.getCenter().lng) };
map.on('move', onMapMove);
onMapMove();
}
});
Там нет сообщения об ошибке, просто пустой экран, где должна была быть карта .... Я не понимаю, почему это происходит, поскольку и необходимый javascript, и html рендерятся, если я меняю их на что-то другое ...
Если есть лучший способ создать этот виджет, этого тоже будет достаточно!
Заранее спасибо!
Основная проблема вашего кода заключается в том, что вы используете устаревший шаблон URL и старые версии листовки.
С другой стороны, нет необходимости загружать html и js в виде текста, QtWebEngine может отображать файл напрямую.
Учитывая вышеизложенное, решение такое:
структура:
├── main.py
└── src
└── main
└── assets
├── map.html
└── map.js
карта.js
var map;
function initialize(){
map = L.map('map').setView([55.61121, 12.99351], 16);
L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: 'Map data © <a href = "http://openstreetmap.org">OpenStreetMap</a> contributors, <a href = "http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href = "http://cloudmade.com">CloudMade</a>',
maxZoom: 18
}).addTo(map);
var marker = L.marker(map.getCenter()).addTo(map);
marker.bindPopup("Hello World!").openPopup();
new QWebChannel(qt.webChannelTransport, function (channel) {
window.MainWindow = channel.objects.MainWindow;
if (typeof MainWindow != 'undefined') {
var onMapMove = function() { MainWindow.onMapMove(map.getCenter().lat, map.getCenter().lng) };
map.on('move', onMapMove);
onMapMove();
}
});
}
карта.html
<!DOCTYPE html>
<html>
<head>
<script src = "qrc:///qtwebchannel/qwebchannel.js"></script>
<script src = "https://unpkg.com/[email protected]/dist/leaflet.js"></script>
<link rel = "stylesheet" href = "https://unpkg.com/[email protected]/dist/leaflet.css" />
<script type = "text/javascript" src = "map.js"></script>
<style>
body { padding: 0; margin: 0; }
html, body, #map { height: 100%; }
</style>
</head>
<body onload = "initialize()">
<div id = "map"></div>
</body>
</html>
main.py
import os
import functools
from PyQt5 import QtCore, QtGui, QtWidgets, QtWebEngineWidgets, QtWebChannel
class MainWindow(QtWidgets.QWidget):
def __init__(self):
super(MainWindow, self).__init__()
self.setupUi()
def setupUi(self):
# self.setFixedSize(800, 500)
vbox = QtWidgets.QVBoxLayout()
self.setLayout(vbox)
label = self.label = QtWidgets.QLabel()
sp = QtWidgets.QSizePolicy()
sp.setVerticalStretch(0)
label.setSizePolicy(sp)
vbox.addWidget(label)
view = self.view = QtWebEngineWidgets.QWebEngineView()
channel = self.channel = QtWebChannel.QWebChannel()
channel.registerObject("MainWindow", self)
view.page().setWebChannel(channel)
file = os.path.join(
os.path.dirname(os.path.realpath(__file__)),
"src/main/assets/map.html",
)
self.view.setUrl(QtCore.QUrl.fromLocalFile(file))
vbox.addWidget(view)
button = QtWidgets.QPushButton("Go to Paris")
panToParis = functools.partial(self.panMap, 2.3272, 48.8620)
button.clicked.connect(panToParis)
vbox.addWidget(button)
@QtCore.pyqtSlot(float, float)
def onMapMove(self, lat, lng):
self.label.setText("Lng: {:.5f}, Lat: {:.5f}".format(lng, lat))
def panMap(self, lng, lat):
page = self.view.page()
page.runJavaScript("map.panTo(L.latLng({}, {}));".format(lat, lng))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
Выход:
Работал как шарм! Спасибо!