OpenLayers PyQt 5.9中的地理位置

问题描述:

我已经实现了一个具有地理定位功能和按钮的网站。OpenLayers PyQt 5.9中的地理位置

该网页在QwebEngineView(OSM Map也可以)中显示得很好。 在网页加载

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')) 

所有本地的OpenLayers按钮(ZOOM IN和OUT)工作正常。

我创建了一个新的自定义按钮来在OpenLayers地图上显示我的地理位置。

这是使用来地理定位我的IM功能:

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] 
     }) 
     }); 
    } 

我创建的按钮与here帮助。

整个网页看起来是这样的:

<!DOCTYPE html> 
<html> 
    <head> 
    <title>Accessible Map</title> 
    <link rel="stylesheet" href="https://openlayers.org/en/v4.2.0/css/ol.css" type="text/css"> 
    <!-- The line below is only needed for old environments like Internet Explorer and Android 4.x --> 
    <script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=requestAnimationFrame,Element.prototype.classList,URL"></script> 
    <script src="https://openlayers.org/en/v4.2.0/build/ol-debug.js"></script> 
    <style> 
     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; 
     } 
    </style> 
    </head> 
    <body> 
    <div id="map" class="map" tabindex="0"></div> 
    <script> 
     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 
    </script> 
    </body> 
</html> 

内部正常的浏览器,它工作正常,但不是我的PyQt的应用程序内。 点击自定义按钮后没有任何反应。

我在做什么错误或不可能?

+0

你能解释一下你得到什么错误或不必要的行为。 – eyllanesc

+0

什么都没有发生,而不是放大到我的地理位置 – Trevirius

+0

你可以显示[最小,完整和可验证的例子](https://*.com/help/mcve),即Python代码,而不是它需要运行它。 – eyllanesc

主要问题是启用权限,如果您在Firefox,Chrome等浏览器中运行,会向您显示一个弹出窗口,要求您接受或不接受GeoLocation权限。

在这种情况下,必须通过代码启用,这样做的QWebEnginePage发出需要每次授权的信号,它这样做通过信号featurePermissionRequested,我们将它连接到一些槽,我们能够与功能setFeaturePermission()许可。

self.ui.w3View..page().featurePermissionRequested.connect(self.onFeaturePermissionRequested) 

def onFeaturePermissionRequested(self, securityOrigin, feature): 
    self.sender().setFeaturePermission(securityOrigin, 
            QWebEnginePage.Geolocation, 
            QWebEnginePage.PermissionGrantedByUser) 

:在linux下我仍然有与GeoClude供应商的问题,错误信息如下:

Failed to set Geoclue positioning requirements. Geoclue error: org.qtproject.QtDBus.Error.InvalidObjectPath

+0

有时会在控制台中显示: serialnmea:找不到已知的GPS设备。通过QT_NMEA_SERIAL_PORT指定COM端口。 – Trevirius

添加以下行解决了我的问题:

self.ui.w3View.page().featurePermissionRequested.connect(self.permissionRequested) 

def permissionRequested(self, frame, feature): 
    self.ui.w3View.page().setFeaturePermission(frame, feature, QtWebEngineWidgets.QWebEnginePage().PermissionGrantedByUser) 

this后发现它并编辑到PyQt的5.9。

+0

这就是我的代码所做的。 – eyllanesc

+0

im对不起,没有正确地读取导入线 – Trevirius

+0

我认为这个答案必须是我的,除了我可以正确支持,你会让我发布我的答案。在Windows上的 – eyllanesc