【问题标题】:Viewing maps with PyQt4 QWebView using python 3使用 python 3 使用 PyQt4 QWebView 查看地图
【发布时间】:2017-08-30 23:37:41
【问题描述】:

我正在构建一个程序,可以根据数据库中的特定坐标显示带有标记的地图,所以过程是:

  1. 使用 (folium) 从 osm 获取地图
  2. 添加标记
  3. 将地图另存为 HTML
  4. 在 QWebView 中显示 map.html。

但如果坐标总是在变化,例如(车辆跟踪系统),这种方式是不切实际的。

有没有什么方法可以让我在地图上添加或更新标记,避免前面的过程,而不必创建 map.html 文件然后将其加载到 QWebView 然后每次都显示它。

谢谢

【问题讨论】:

    标签: python python-3.x pyqt pyqt4 openstreetmap


    【解决方案1】:

    前段时间,我创建了一个小型库,用于使用 PyQt 和 Google MapsOpenStreetMap 在地图中显示标记,由于您的问题,我添加了此功能,因此您可以从此 link 下载代码并尝试示例:qOSMExample2.py

    在这个答案中,我将向您展示我的代码中最重要的部分,以便您可以添加自定义功能。

    QWebView 支持 javascript,所以我使用了小册子库,它包含在 html 中,如下所示:

    <!DOCTYPE html>
    <html>
    <head>
        <meta name="viewport" content="initial-scale=1.0, user-scalable=no"/>
    
    
        <style type="text/css">
    			html { height: 100%; }
    			body { height: 100%; margin: 0; padding: 0 }
    			#mapid { height: 100% }
        </style>
    
        <link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.3/dist/leaflet.css"
              integrity="sha512-07I2e+7D8p6he1SIM+1twR5TIrhUQn9+I6yjqD53JQjFiMf8EtC93ty0/5vJTZGF8aAocvHYNEDJajGdNx1IsQ=="
              crossorigin=""/>
    
        <script src="https://unpkg.com/leaflet@1.0.3/dist/leaflet.js"
                integrity="sha512-A7vV8IFfih/D732iSSKi20u/ooOfj/AGehOKq0f4vLT1Zr2Y+RX7C+w8A1gaSasGtRUZpF/NZgzSAu4/Gc41Lg=="
                crossorigin=""></script>
    
        <script type="text/javascript" src="qOSM.js"></script>
    </head>
    <body onload="initialize()">
    <div id="mapid" style="width:100%; height:100%"></div>
    </body>
    </html>

    另外,如果我们观察到我已经导入了 qOSM.js 文件,该文件实现了创建、移动地图和标记的逻辑。

    另一个重要的是将python与javascript交互,因为pyqt为我们提供了2个功能:

    void QWebFrame::addToJavaScriptWindowObject(const QString & name, QObject * object)

    在框架的 JavaScript 中使对象在名称下可用 语境。该对象将作为框架窗口的子项插入 目的。 [...]

    self.page().mainFrame().addToJavaScriptWindowObject("qtWidget", self)
    

    QVariant QWebFrame::evaluateJavaScript(const QString & scriptSource)

    使用此框架评估由 scriptSource 定义的 JavaScript 上下文并返回最后执行语句的结果。

    def runScript(self, script):
        return self.page().mainFrame().evaluateJavaScript(script)
    

    第一个函数允许我们在 js 中嵌入一个 python 对象,这样我们就可以从 js 输出信号并将它们连接到 python 插槽。二是面向执行js的函数,接收返回的。总之,第一个用于异步获取答案,第二个用于同步获取答案。

    在下一部分中,我将展示实现上述功能的js:

    // Where you want to render the map.
    
    var map;
    
    var markers = [];
    
    var LeafIcon;
    
    function initialize() {
        var element = document.getElementById('mapid');
    
        map = L.map(element);
    
        L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
            attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
        }).addTo(map);
    
        if (typeof qtWidget !== 'undefined') {
    
            map.on('dragend', function () {
                center = map.getCenter();
                qtWidget.mapMoved(center.lat, center.lng);
            });
    
            map.on('click', function (ev) {
                qtWidget.mapClicked(ev.latlng.lat, ev.latlng.lng);
            });
    
            map.on('dblclick', function (ev) {
                qtWidget.mapDoubleClicked(ev.latlng.lat, ev.latlng.lng);
            });
    
            map.on('contextmenu', function (ev) {
                qtWidget.mapRightClicked(ev.latlng.lat, ev.latlng.lng);
            });
        }
    
        LeafIcon = L.Icon.extend({
            options: {
                shadowUrl: 'leaf-shadow.png',
                iconSize: [38, 95],
                shadowSize: [50, 64],
                iconAnchor: [22, 94],
                shadowAnchor: [4, 62],
                popupAnchor: [-3, -76]
            }
        });
    }
    
    function osm_setCenter(lat, lng) {
        //console.log(lat);
        map.panTo(new L.LatLng(lat, lng));
    }
    
    function osm_getCenter() {
        return map.getCenter();
    }
    
    function osm_setZoom(zoom) {
        map.setZoom(zoom);
    }
    
    function osm_addMarker(key, latitude, longitude, parameters) {
    
        if (key in markers) {
            osm_deleteMarker(key);
        }
    
        if ("icon" in parameters) {
    
            parameters["icon"] = new L.Icon({
                iconUrl: parameters["icon"],
                iconAnchor: new L.Point(16, 16)
            });
        }
    
        var marker = L.marker([latitude, longitude], parameters).addTo(map);
    
        if (typeof qtWidget !== 'undefined') {
    
            marker.on('dragend', function (event) {
                var marker = event.target;
                qtWidget.markerMoved(key, marker.getLatLng().lat, marker.getLatLng().lng);
            });
    
            marker.on('click', function (event) {
                var marker = event.target;
                //marker.bindPopup(parameters["title"]);
                qtWidget.markerClicked(key, marker.getLatLng().lat, marker.getLatLng().lng);
            });
    
            marker.on('dbclick', function (event) {
                var marker = event.target;
                qtWidget.markerClicked(key, marker.getLatLng().lat, marker.getLatLng().lng);
            });
    
            marker.on('contextmenu', function (event) {
                var marker = event.target;
                qtWidget.markerRightClicked(key, marker.getLatLng().lat, marker.getLatLng().lng);
            });
        }
    
        markers[key] = marker;
        return key;
    }
    
    function osm_deleteMarker(key) {
        map.removeLayer(markers[key]);
        delete markers[key];
    }
    
    function osm_moveMarker(key, latitude, longitude) {
        marker = markers[key];
        var newLatLng = new L.LatLng(latitude, longitude);
        marker.setLatLng(newLatLng);
    }
    
    function osm_posMarker(key) {
        marker = markers[key];
        return [marker.getLatLng().lat, marker.getLatLng().lng];
    }
    
    
    http://

    输出:

    【讨论】:

    • 非常感谢您的回答,这正是我想要的:)。我对你的库做了一些修改,它对我有用。
    • @eyllanesc 我从 github 下载了您的代码,但收到以下错误 ModuleNotFoundError: No module named 'PyQt5.QtWebKit'。除了PyQt5qgmap,我应该安装另一个库吗?感谢您的帮助。
    • @H.Dave 你有什么版本的 PyQt5?你做了什么例子?
    • @eyllanesc 我有PyQt5==5.9.1 版本,我试过qGmapExample
    • @H.Dave 我将从 QWebEngineView 升级,但在此之前告诉我是否可以执行以下命令:from PyQt5.QtWebEngineWidgets import QWebEngineView
    猜你喜欢
    • 1970-01-01
    • 2023-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-26
    相关资源
    最近更新 更多