He implementado un sitio web con una función de geolocalización y un botón.
Esta página web se muestra bien en un QwebEngineView (OSM Map también). La pagina web esta cargada
def __init__(self, parent=None): super(MainGUI, self).__init__(parent) self.ui = uic.loadUi("GPS.ui", self) self.ui.w3View.load(QtCore.QUrl('file:///Map.html'))
Todos los botones nativos de OpenLayers (Zoom IN y OUT) funcionan bien.
Creé un nuevo botón personalizado para mostrar mi geolocalización en el mapa de OpenLayers.
Esta es la función que estoy usando para geolocalizarme:
var handleGeolocation = function() { var coordinates; var geolocation = new ol.Geolocation({ projection: view.getProjection(), tracking: true }); // handle geolocation error. geolocation.on('error', function (error) { var info = document.getElementById('info'); info.innerHTML = error.message; info.style.display = ''; }); var accuracyFeature = new ol.Feature(); geolocation.on('change:accuracyGeometry', function () { accuracyFeature.setGeometry(geolocation.getAccuracyGeometry()); }); var positionFeature = new ol.Feature(); positionFeature.setStyle(new ol.style.Style({ image: new ol.style.Circle({ radius: 6, fill: new ol.style.Fill({ color: '#3399CC' }), stroke: new ol.style.Stroke({ color: '#fff', width: 2 }) }) })); geolocation.once('change:position', function () { coordinates = geolocation.getPosition(); positionFeature.setGeometry(coordinates ? new ol.geom.Point(coordinates) : null); map.getView().setCenter(coordinates); map.getView().setZoom(17); }); new ol.layer.Vector({ map: map, source: new ol.source.Vector({ features: [accuracyFeature, positionFeature] }) }); }
He creado el botón con la ayuda de aquí .
toda la página web se ve así:
Accessible Map a.skiplink { position: absolute; clip: rect(1px, 1px, 1px, 1px); padding: 0; border: 0; height: 1px; width: 1px; overflow: hidden; } a.skiplink:focus { clip: auto; height: auto; width: auto; background-color: #fff; padding: 0.3em; } #map:focus { outline: #4A74A8 solid 0.15em; } map{ max-width: 760 px; max-height: 50 px; } .geoButton { top: 80px; left: .5em; } window.app = {}; var app = window.app; view = new ol.View({ center: [0, 0], zoom: 2 }); app.getLocation = function(opt_options) { var options = opt_options || {}; var geoButton = document.createElement('button'); geoButton.innerHTML = 'L'; var handleGeolocation = function() { /* var isMobile = { Android: function () { return navigator.userAgent.match(/Android/i); }, BlackBerry: function () { return navigator.userAgent.match(/BlackBerry/i); }, iOS: function () { return navigator.userAgent.match(/iPhone|iPod|iPad/i); }, Opera: function () { return navigator.userAgent.match(/Opera Mini/i); }, Windows: function () { return navigator.userAgent.match(/IEMobile/i); }, any: function () { return ((isMobile.Android() || isMobile.BlackBerry() || isMobile.iOS() || isMobile.Opera() || isMobile.Windows())); } }; if (isMobile.any()){ geolocation.setTrackingOptions(enableHighAccuracy ); } */ var coordinates; var geolocation = new ol.Geolocation({ projection: view.getProjection(), tracking: true }); // handle geolocation error. geolocation.on('error', function (error) { var info = document.getElementById('info'); info.innerHTML = error.message; info.style.display = ''; }); var accuracyFeature = new ol.Feature(); geolocation.on('change:accuracyGeometry', function () { accuracyFeature.setGeometry(geolocation.getAccuracyGeometry()); }); var positionFeature = new ol.Feature(); positionFeature.setStyle(new ol.style.Style({ image: new ol.style.Circle({ radius: 6, fill: new ol.style.Fill({ color: '#3399CC' }), stroke: new ol.style.Stroke({ color: '#fff', width: 2 }) }) })); geolocation.once('change:position', function () { coordinates = geolocation.getPosition(); positionFeature.setGeometry(coordinates ? new ol.geom.Point(coordinates) : null); map.getView().setCenter(coordinates); map.getView().setZoom(17); }); new ol.layer.Vector({ map: map, source: new ol.source.Vector({ features: [accuracyFeature, positionFeature] }) }); } geoButton.addEventListener('click', handleGeolocation, false); geoButton.addEventListener('touchstart', handleGeolocation, false); var element = document.createElement('div'); element.className = 'ol-unselectable ol-control geoButton'; element.appendChild(geoButton); ol.control.Control.call(this, { element: element, target: options.target }); }; ol.inherits(app.getLocation, ol.control.Control); //Standard Initialisierung // Geolocation function var map = new ol.Map({ layers: [ new ol.layer.Tile({ source: new ol.source.OSM() }) ], target: 'map', controls: ol.control.defaults({ attributionOptions: /** @type {olx.control.AttributionOptions} */ ({ collapsible: false }) }).extend([new app.getLocation()]), view: view }); //Display Input Datastream
Dentro de un navegador normal funciona bien pero no dentro de mi aplicación PyQt. Después de hacer clic en el botón personalizado no pasa nada.
¿Qué estoy haciendo mal o no es posible?
El principal problema es habilitar los permisos, si ejecuta en un navegador como Firefox, Chrome, etc., se le mostrará una ventana emergente solicitándole que acepte o no el permiso de GeoLocation.
En este caso, debe estar habilitado por código, para esto la QWebEnginePage
emite una señal cada vez que se requiere autorización, lo hace a través de la función de señal featurePermissionRequested
, la conectamos a alguna ranura y habilitamos el permiso con la función setFeaturePermission()
.
self.ui.w3View..page().featurePermissionRequested.connect(self.onFeaturePermissionRequested) def onFeaturePermissionRequested(self, securityOrigin, feature): self.sender().setFeaturePermission(securityOrigin, QWebEnginePage.Geolocation, QWebEnginePage.PermissionGrantedByUser)
Nota : en Linux todavía tengo problemas con el proveedor de GeoClude, el mensaje de error es el siguiente:
Error al establecer los requisitos de posicionamiento Geoclue. Error de geoclue: org.qtproject.QtDBus.Error.InvalidObjectPath
Añadiendo las siguientes líneas resolví mis problemas:
self.ui.w3View.page().featurePermissionRequested.connect(self.permissionRequested) def permissionRequested(self, frame, feature): self.ui.w3View.page().setFeaturePermission(frame, feature, QtWebEngineWidgets.QWebEnginePage.PermissionGrantedByUser)
Lo encontré en este post y lo edité en PyQt 5.9.