我想开发一个桌面应用程序,涉及每秒从串行端口接收一个地理坐标并实时添加到地图中。地图应类似于以下链接:
我编写了一段代码来测试 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 关于不可能无缝更新生成的大叶植物地图,似乎使用 ClickForMarker() 可以向渲染的地图添加标记。
有没有办法在不点击的情况下获得相同的功能?
答案 0 :(得分:2)
您可以通过 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()