PyQt 5.9 中的 OpenLayers 地理定位
Posted
技术标签:
【中文标题】PyQt 5.9 中的 OpenLayers 地理定位【英文标题】:OpenLayers Geolocation in PyQt 5.9 【发布时间】:2017-08-15 08:55:23 【问题描述】:我已经实现了一个带有地理定位功能和按钮的网站。
此网页在 QwebEngineView(OSM 地图)中显示良好。 网页已加载
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 按钮(放大和缩小)都可以正常工作。
我创建了一个新的自定义按钮来在 OpenLayers 地图上显示我的地理位置。
这是我用来定位我的功能:
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 应用程序中却不行。 单击自定义按钮后没有任何反应。
我做错了什么或不可能?
【问题讨论】:
你可以解释你得到了什么错误或不需要的行为。 什么都没有发生,而不是放大我的地理位置 您可以显示Minimal, Complete, and Verifiable example,即python 代码,而不是运行它所需的内容。 你的操作系统是什么? 在 linux 中我的位置提供程序有问题,可能在您的操作系统中没有这个问题,请尝试我的代码:gist.github.com/eyllanesc/12d82588c3d56bb00ecf5d3d300c92ef 【参考方案1】:主要问题是启用权限,如果您在 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 provider的问题,报错信息如下:
未能设置 Geoclue 定位要求。地理线索错误: org.qtproject.QtDBus.Error.InvalidObjectPath
【讨论】:
在 Windows 上有时会在控制台中显示:serialnmea:未找到已知的 GPS 设备。通过 QT_NMEA_SERIAL_PORT 指定 COM 端口。【参考方案2】:添加以下行解决了我的问题:
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。
【讨论】:
以上是关于PyQt 5.9 中的 OpenLayers 地理定位的主要内容,如果未能解决你的问题,请参考以下文章