I am building a program that can show a map with a markers according to specific coordinates from a database, so the process is:
Some time ago I had created a small library to show markers in maps using PyQt and Google Maps or OpenStreetMap, because of your question I added this functionality so you can download the code from this link and try the example: qOSMExample2.py
In this answer I'll show you the most important parts of my code so that you can add custom functionality.
QWebView supports javascript so I used the leaflet library, and this is included in the html as shown below:
<!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>
In addition if we observe I have imported the qOSM.js file that implements the logic of creating, moving the map and the same with the markers.
The other important is to interact python with javascript for it pyqt offers us 2 functions:
void QWebFrame::addToJavaScriptWindowObject(const QString & name, QObject * object)
Make object available under name from within the frame's JavaScript context. The object will be inserted as a child of the frame's window object. [...]
self.page().mainFrame().addToJavaScriptWindowObject("qtWidget", self)
QVariant QWebFrame::evaluateJavaScript(const QString & scriptSource)
Evaluates the JavaScript defined by scriptSource using this frame as context and returns the result of the last executed statement.
def runScript(self, script):
return self.page().mainFrame().evaluateJavaScript(script)
The first function allows us to embed a python object in js and so we can output signals from js and connect them to python slots. The second is oriented to execute functions of js and receive what returns. In summary the first one serves to obtain answers asynchronously and the second one synchronously.
In the next part I show the js where the functions mentioned above are implemented:
// 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: '© <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://
Output: