Skip to main content
 首页 » 编程设计

python之创建一个开放的街道 map View

2024年09月03日33dflying

我正在尝试移植此代码:https://gist.github.com/ataffanel/13aac4b79bc0080b881f到最新版本的 pyqt5,因此,使用 qtwebengine。目标只是最终有一个 map 小部件。

这是我已有的代码,使用随机 html 和 javascript 运行它可以工作,但我无法获得 map View 原始代码的意图。

主要.py:

 
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_() 

map .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> 

map .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 &copy; <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(); 
    } 
}); 

没有错误消息,只有一个空白屏幕,它应该是一张 map ....我不明白为什么会发生这种情况,因为如果我将它们更改为其他内容,则必要的 javascript 和 html 都会呈现...

如果有更好的方法来创建这个小部件也足够了!

提前致谢!

请您参考如下方法:

您的代码存在的主要问题是您使用的是已弃用的 URL 模板和旧版本的传单。

另一方面,无需将 html 和 js 作为文本加载,QtWebEngine 可以直接显示文件。

综合以上,解决方案是:

结构:

├── main.py 
└── src 
    └── main 
        └── assets 
            ├── map.html 
            └── map.js 

map .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 &copy; <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(); 
        } 
    }); 
} 

map .html

<!DOCTYPE html> 
<html> 
<head> 
    <script src="qrc:///qtwebchannel/qwebchannel.js"></script> 
    <script src="https://unpkg.com/leaflet@1.0.2/dist/leaflet.js"></script> 
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.2/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> 

主.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_()) 

输出: