【问题标题】:How add circle markers to a rendered folium map embedded in a QWebEngineView?如何将圆形标记添加到嵌入在 QWebEngineView 中的渲染叶图?
【发布时间】:2021-10-07 09:38:05
【问题描述】:

我想开发一个桌面应用程序,该应用程序涉及每秒从串行端口接收地理坐标并实时添加到地图中。地图应类似于以下链接:

我编写了一段代码来测试 Folium 执行此任务的能力。

import sys
import io
import folium
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QMainWindow, QPushButton
from PyQt5.QtWebEngineWidgets import QWebEngineView


class Window(QMainWindow):
    def __init__(self):
        super().__init__()

        coordinate = (41.8828, 12.4761)

        self.m = folium.Map(
            zoom_start = 18,
            location = coordinate,
            control_scale=True,
            tiles = None
        )

        folium.raster_layers.TileLayer(
            tiles='http://mt1.google.com/vt/lyrs=m&h1=p1Z&x={x}&y={y}&z={z}',
            name='Standard Roadmap',
            attr = 'Google Map',
        ).add_to(self.m)

        folium.raster_layers.TileLayer(
            tiles='http://mt1.google.com/vt/lyrs=s&h1=p1Z&x={x}&y={y}&z={z}',
            name='Satellite Only',
            attr = 'Google Map',
        ).add_to(self.m)

        folium.raster_layers.TileLayer(
            tiles='http://mt1.google.com/vt/lyrs=y&h1=p1Z&x={x}&y={y}&z={z}',
            name='Hybrid',
            attr = 'Google Map',
        ).add_to(self.m)      

        folium.LayerControl().add_to(self.m)

        folium.Marker(coordinate).add_to(self.m)
                                
        self.data = io.BytesIO()
        self.m.save(self.data, close_file=False)

        widget=QWidget()
        vbox = QVBoxLayout()

        buttun1 = QPushButton("Insert Marker")
        buttun1.clicked.connect(self.insert_marker)

        self.webView = QWebEngineView()
        self.webView.setHtml(self.data.getvalue().decode())
        self.webView.setContextMenuPolicy(Qt.NoContextMenu)
    
        vbox.addWidget(buttun1)
        vbox.addWidget(self.webView)
        widget.setLayout(vbox)
        
        self.setCentralWidget(widget)
        
        self.setWindowTitle("App")
        
        self.setMinimumSize(1000, 600)
        self.showMaximized()

    def insert_marker(self):
        folium.CircleMarker([41.8829, 12.4766],
            radius=2,
            weight=5,
        ).add_to(self.m)  
        self.m.save(self.data, close_file=False)
        self.webView.setHtml(self.data.getvalue().decode())
       

App = QApplication(sys.argv)
window = Window()
sys.exit(App.exec())

在这段代码中,folium 地图嵌入在一个 PyQt5 QWebEngineView 中,点击上面的按钮后,预计会在地图中添加一个圆形标记。但是,点击后,地图只会重新渲染。

尽管有一些discussions 表示无法无缝更新生成的 folium 地图,但似乎使用 ClickForMarker() 可以将标记添加到渲染地图。

有没有办法在不点击的情况下获得相同的功能?

【问题讨论】:

    标签: python pyqt5 folium python-3.9 qwebengineview


    【解决方案1】:

    您可以通过runJavaScript()方法执行javascript来添加标记:

    import io
    import sys
    
    from jinja2 import Template
    
    import folium
    
    from PyQt5.QtCore import pyqtSignal, QObject, QTimer
    from PyQt5.QtWidgets import QApplication, QMainWindow
    from PyQt5.QtWebEngineWidgets import QWebEngineView
    
    
    class CoordinateProvider(QObject):
        coordinate_changed = pyqtSignal(float, float)
    
        def __init__(self, parent=None):
            super().__init__(parent)
            self._timer = QTimer(interval=1000)
            self._timer.timeout.connect(self.generate_coordinate)
    
        def start(self):
            self._timer.start()
    
        def stop(self):
            self._timer.stop()
    
        def generate_coordinate(self):
            import random
    
            center_lat, center_lng = 41.8828, 12.4761
            x, y = (random.uniform(-0.001, 0.001) for _ in range(2))
            latitude = center_lat + x
            longitude = center_lng + y
            self.coordinate_changed.emit(latitude, longitude)
    
    
    class Window(QMainWindow):
        def __init__(self):
            super().__init__()
            coordinate = (41.8828, 12.4761)
            self.map = folium.Map(
                zoom_start=18, location=coordinate, control_scale=True, tiles=None
            )
            folium.raster_layers.TileLayer(
                tiles="http://mt1.google.com/vt/lyrs=m&h1=p1Z&x={x}&y={y}&z={z}",
                name="Standard Roadmap",
                attr="Google Map",
            ).add_to(self.map)
            folium.raster_layers.TileLayer(
                tiles="http://mt1.google.com/vt/lyrs=s&h1=p1Z&x={x}&y={y}&z={z}",
                name="Satellite Only",
                attr="Google Map",
            ).add_to(self.map)
            folium.raster_layers.TileLayer(
                tiles="http://mt1.google.com/vt/lyrs=y&h1=p1Z&x={x}&y={y}&z={z}",
                name="Hybrid",
                attr="Google Map",
            ).add_to(self.map)
            folium.LayerControl().add_to(self.map)
            folium.Marker(coordinate).add_to(self.map)
    
            data = io.BytesIO()
            self.map.save(data, close_file=False)
    
            self.map_view = QWebEngineView()
            self.map_view.setHtml(data.getvalue().decode())
    
            self.setCentralWidget(self.map_view)
    
        def add_marker(self, latitude, longitude):
            js = Template(
                """
            L.marker([{{latitude}}, {{longitude}}] )
                .addTo({{map}});
            L.circleMarker(
                [{{latitude}}, {{longitude}}], {
                    "bubblingMouseEvents": true,
                    "color": "#3388ff",
                    "dashArray": null,
                    "dashOffset": null,
                    "fill": false,
                    "fillColor": "#3388ff",
                    "fillOpacity": 0.2,
                    "fillRule": "evenodd",
                    "lineCap": "round",
                    "lineJoin": "round",
                    "opacity": 1.0,
                    "radius": 2,
                    "stroke": true,
                    "weight": 5
                }
            ).addTo({{map}});
            """
            ).render(map=self.map.get_name(), latitude=latitude, longitude=longitude)
            self.map_view.page().runJavaScript(js)
    
    
    def main():
        app = QApplication(sys.argv)
    
        window = Window()
        window.showMaximized()
    
        provider = CoordinateProvider()
        provider.coordinate_changed.connect(window.add_marker)
        provider.start()
    
        sys.exit(app.exec())
    
    
    if __name__ == "__main__":
        main()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-07-24
      • 1970-01-01
      • 2021-12-10
      • 2011-05-15
      • 2018-10-17
      • 2012-05-04
      相关资源
      最近更新 更多