【问题标题】:Creating a open street maps view创建一个开放的街道地图视图
【发布时间】:2019-10-14 12:35:43
【问题描述】:

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

这是我已经拥有的代码,它使用随机 html 和 javascript 运行,但我无法获得原始代码的意图的地图视图。

Main.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();
    }
});

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

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

提前致谢!

【问题讨论】:

    标签: python python-3.x pyqt5 qtwebengine qwebengineview


    【解决方案1】:

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

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

    综合以上,解决办法是:

    结构:

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

    ma​​p.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();
            }
        });
    }
    

    ma​​p.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>
    

    ma​​in.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_())
    

    输出:

    【讨论】:

    • 工作就像一个魅力!谢谢!
    猜你喜欢
    • 1970-01-01
    • 2019-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多