python - 如何将圆形标记添加到嵌入在 QWebEngineView 中的渲染叶图?

标签 python pyqt5 folium python-3.9 qwebengineview

我想开发一个桌面应用程序,该应用程序涉及每秒从串行端口接收地理坐标并实时添加到 map 中。该 map 应类似于以下链接:
enter image description here
我编写了一段代码来测试 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 map 嵌入在一个 PyQt5 QWebEngineView 中,点击上面的按钮后,预计会在 map 中添加一个圆形标记。但是,点击后, map 只会重新渲染。
尽管有一些 discussions关于无法无缝更新生成的folium map ,似乎使用 ClickForMarker() 您可以将标记添加到渲染 map 。
有没有办法在不点击的情况下获得相同的功能?

最佳答案

您可以通过 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()
enter image description here

关于python - 如何将圆形标记添加到嵌入在 QWebEngineView 中的渲染叶图?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68614721/

相关文章:

Python matplotlib - 如何创建用颜色代表频率的饼图?

python - 来自 Python 应用的 Google 搜索

python - 如何通过不单击按钮来调用函数?

folium - Folium 中 map 标记中的数字

python - 如何将 folium.icon 与 fontawesome 一起使用

python - 什么会阻止过滤器返回 0?

python - 在函数头调用@api

python - 圆形 QGraphicsView

python - 使用 PyQt5 将 qDebug 输出重定向到文件

Python Folium Topojson 文件未渲染