[英]storing lat long on mouse click from JS to PyQt5
I'm trying to store lat/lng on mouse click to geometry Point. 我正在尝试在鼠标单击到几何点时存储经纬度。 So basically when user clicks on map i need to get those coordinates(lat/lng) and store them to variable for example
point = Point(lat, lng)
so i can calculate nearest geometry and pull data from PostGIS. 因此,基本上,当用户单击地图时,我需要获取那些坐标(纬度/经度)并将其存储到变量中,例如
point = Point(lat, lng)
以便我可以计算最近的几何图形并从PostGIS中提取数据。
I'm aware i need to establish backend and @pyqtSlot(float,float)
, but since im new to this i cant get it to work. 我知道我需要建立后端和
@pyqtSlot(float,float)
,但是由于这是我的新手,因此我无法使其正常工作。 I have this code that is generated by QtDesigner and you dont have to bother with all the buttons. 我有QtDesigner生成的这段代码,您不必理会所有按钮。 Here is the HTML/JS part:
这是HTML / JS部分:
maphtml = '''
<!DOCTYPE HTML>
<html>
<head>
<meta name="robots" content="index, all" />
<script src="qrc:///qtwebchannel/qwebchannel.js"></script>
<title>WebGL Earth API - Side-by-side - Basic Leaflet
compatibility</title>
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-
0.7.2/leaflet.css" />
<script src="http://cdn.leafletjs.com/leaflet-0.7.2/leaflet.js"></script>
<script src="http://www.webglearth.com/v2/api.js"></script>
<script src="scripts/qwebchannel.js"></script>
<script>
var backend;
new QWebChannel(qt.webChannelTransport, function (channel) {
backend = channel.objects.backend;
});
function init() {
var m = {};
start_(L, 'L');
start_(WE, 'WE');
function start_(API, suffix) {
var mapDiv = 'map' + suffix;
var map = API.map(mapDiv, {
center: [51.505, -0.09],
zoom: 4,
dragging: true,
scrollWheelZoom: true,
proxyHost: 'http://srtm.webglearth.com/cgi-bin/corsproxy.fcgi?url='
});
m[suffix] = map;
//Add baselayer
API.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',{
attribution: '© OpenStreetMap contributors'
}).addTo(map);
//Add TileJSON overlay
var json = {"profile": "mercator", "name": "Grand Canyon USGS", "format":
"png", "bounds": [15.976953506469728, 45.813157465613884], "minzoom": 10,
"version": "1.0.0", "maxzoom": 16, "center": [15.976953506469728,
45.813157465613884, 16], "type": "overlay", "description": "",
"basename":
"grandcanyon", "tilejson": "2.0.0", "sheme": "xyz", "tiles":
["http://tileserver.maptiler.com/grandcanyon/{z}/{x}/{y}.png"]};
if (API.tileLayerJSON) {
var overlay2 = API.tileLayerJSON(json, map);
} else {
//If not able to display the overlay, at least move to the same location
map.setView([json.center[1], json.center[0]], json.center[2]);
}
//Print coordinates of the mouse
map.on('click', function(e) {
document.getElementById('coords').innerHTML = e.latlng.lat + ', ' +
e.latlng.lng;
backend.foo(e.latlng.lat,e.latlng.lng)
});
}
//Synchronize view
m['L'].on('click', function(e) {
var center = m['L'].getCenter();
var zoom = m['L'].getZoom();
m['WE'].setView([center['lat'], center['lng']], zoom);
});
}
</script>
<style>
html, body{padding: 0; margin: 0; overflow: hidden;}
#mapL, #mapWE {position:absolute !important; top: 0; right: 0; bottom: 0;
left: 0;
background-color: #fff; position: absolute !important;}
#mapL {right: 0%;}
#mapWE {left: 100%;}
#coords {position: absolute; bottom: 0;}
</style>
</head>
<body onload="javascript:init()">
<div id="mapL"></div>
<div id="mapWE"></div>
<div id="coords"></div>
</body>
</html>
'''
And here is PyQt code, they are all in same .py btw. 这是PyQt代码,它们都在同一.py btw中。 At the start i have
Backend()
that should be doin its job. 首先,我应该在其工作中使用
Backend()
。 You can skip to def setupUI
and to self.mapa = QtWidgets.QWidget(self.centralwidget)
to see where i call Backend()
: 您可以跳过以
def setupUI
并跳转到self.mapa = QtWidgets.QWidget(self.centralwidget)
来查看我在哪里调用Backend()
:
class Backend(QObject):
@pyqtSlot(float,float)
def foo(self, lat,lng):
global x,y
x=lng
y=lat
print(lat, lng)
class Ui_MainWindow(object):
def selected(self, text):
self.selected_text = text
return self.selected_text
def connecti(self):
try:
engine =
create_engine('postgresql://postgres:hrvatina@localhost:5432/Diplomski')
self.connection = engine.connect()
return QMessageBox.information(None, "Uspješna konekcija",
"Spojeni ste na bazu")
except:
return QMessageBox.critical(None, "Pogreška", "Neuspješno
spajanje na bazu")
def odabir(self):
try:
broj = self.link.text()
self.comboBox.activated[str].connect(self.selected)
value = str(self.comboBox.currentText())
if self.pon.isChecked():
radio = str(self.pon.text())
print(radio)
elif self.uto.isChecked():
radio = str(self.uto.text())
print(radio)
elif self.sri.isChecked():
radio = str(self.sri.text())
print(radio)
elif self.cet.isChecked():
radio = str(self.cet.text())
print(radio)
elif self.pet.isChecked():
radio = str(self.pet.text())
print(radio)
elif self.sub.isChecked():
radio = str(self.sub.text())
print(radio)
elif self.ned.isChecked():
radio = str(self.ned.text())
print(radio)
query ='SELECT * FROM ' + radio + '_' + value + ' where "IdLink"
= %s' % (broj)
df = pd.read_sql_query(query, con=self.connection, params=
{'link': '%' + broj + '%'})
df = df.transpose()
hf = df.join(df.iloc[:, 0].str.split(';', 3,
expand=True).rename(columns={0: 'mean', 1: 'median', 2: 'std'}))
g = hf.drop(hf.columns[[0]], axis=1)
hm = g.drop(g.index[[0]])
prva1 = hm.apply(pd.to_numeric, errors='coerce')
#Izračun srednjih vrijednosti
mean=prva1['mean'].mean()
self.mean.setText(str(mean))
median=prva1['median'].mean()
self.median.setText(str(median))
std=prva1['std'].mean()
self.std.setText(str(std))
upper_bound = go.Scatter(
name='Gornja granica',
x=prva1.index.to_native_types(),
y=prva1['mean'] + prva1['std'],
mode='lines',
marker=dict(color="028F1E"),
line=dict(width=1, color="028F1E"),
fillcolor='rgba(68, 68, 68, 0.3)',
fill='tonexty')
trace = go.Scatter(
name='Srednja vrijednost',
x=prva1.index.to_native_types(),
y=prva1['mean'],
mode='lines',
line=dict(color='rgb(31, 119, 180)'),
fillcolor='rgba(68, 68, 68, 0.3)',
fill='tonexty')
lower_bound = go.Scatter(
name='Donja granica',
x=prva1.index.to_native_types(),
y=prva1['mean'] - prva1['std'],
marker=dict(color="9B111E"),
line=dict(width=1, color="9B111E"),
mode='lines')
data = [lower_bound, trace, upper_bound]
layout = go.Layout(
xaxis=dict(
title='AXIS TITLE',
titlefont=dict(
family='Arial, sans-serif',
size=18,
color='lightgrey'
),
showticklabels=True,
tickangle=45,
tickfont=dict(
family='Old Standard TT, serif',
size=14,
color='black'
),
exponentformat='e',
showexponent='All'
),
yaxis=dict(title='Brzina (km/h)'),
title='Minutni interval za ' + radio + ' sa standardnom
devijacijom za ' + broj,
)
fig = go.Figure(data=data, layout=layout)
raw_html = '<html><head><meta charset="utf-8" />'
raw_html += '<script src="https://cdn.plot.ly/plotly-
latest.min.js"></script></head>'
raw_html += '<body>'
raw_html += plotly.offline.plot(fig, include_plotlyjs=False,
output_type='div')
raw_html += '</body></html>'
#PLOTLY
self.graf.setHtml(raw_html)
except:
return QMessageBox.critical(None, "Pogreška", "Podaci za odabrane
opcije ne postoje!")
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(978, 704)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.formLayout = QtWidgets.QFormLayout(self.centralwidget)
self.formLayout.setObjectName("formLayout")
self.verticalLayout = QtWidgets.QVBoxLayout()
self.verticalLayout.setObjectName("verticalLayout")
self.gumb_spoji = QtWidgets.QPushButton(self.centralwidget)
self.gumb_spoji.setObjectName("gumb_spoji")
# Spoji se na bazu
self.gumb_spoji.clicked.connect(self.connecti)
engine =
self.verticalLayout.addWidget(self.gumb_spoji)
self.link = QtWidgets.QLineEdit(self.centralwidget)
self.link.setObjectName("link")
self.verticalLayout.addWidget(self.link)
self.pon = QtWidgets.QRadioButton(self.centralwidget)
self.pon.setObjectName("pon")
self.verticalLayout.addWidget(self.pon)
self.uto = QtWidgets.QRadioButton(self.centralwidget)
self.uto.setObjectName("uto")
self.verticalLayout.addWidget(self.uto)
self.sri = QtWidgets.QRadioButton(self.centralwidget)
self.sri.setObjectName("sri")
self.verticalLayout.addWidget(self.sri)
self.cet = QtWidgets.QRadioButton(self.centralwidget)
self.cet.setObjectName("cet")
self.verticalLayout.addWidget(self.cet)
self.pet = QtWidgets.QRadioButton(self.centralwidget)
self.pet.setObjectName("pet")
self.verticalLayout.addWidget(self.pet)
self.sub = QtWidgets.QRadioButton(self.centralwidget)
self.sub.setObjectName("sub")
self.verticalLayout.addWidget(self.sub)
self.ned = QtWidgets.QRadioButton(self.centralwidget)
self.ned.setObjectName("ned")
self.verticalLayout.addWidget(self.ned)
self.comboBox = QtWidgets.QComboBox(self.centralwidget)
self.comboBox.setObjectName("comboBox")
self.comboBox.addItem("")
self.comboBox.addItem("")
self.verticalLayout.addWidget(self.comboBox)
self.gumb_dohvati = QtWidgets.QPushButton(self.centralwidget)
self.gumb_dohvati.setObjectName("gumb_dohvati")
# Dohvati podatke
self.gumb_dohvati.clicked.connect(self.odabir)
self.verticalLayout.addWidget(self.gumb_dohvati)
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setObjectName("label")
self.verticalLayout.addWidget(self.label)
self.mean = QtWidgets.QLineEdit(self.centralwidget)
self.mean.setObjectName("mean")
self.verticalLayout.addWidget(self.mean)
self.label_2 = QtWidgets.QLabel(self.centralwidget)
self.label_2.setObjectName("label_2")
self.verticalLayout.addWidget(self.label_2)
self.median = QtWidgets.QLineEdit(self.centralwidget)
self.median.setObjectName("median")
self.verticalLayout.addWidget(self.median)
self.label_3 = QtWidgets.QLabel(self.centralwidget)
self.label_3.setObjectName("label_3")
self.verticalLayout.addWidget(self.label_3)
self.std = QtWidgets.QLineEdit(self.centralwidget)
self.std.setObjectName("std")
self.verticalLayout.addWidget(self.std)
self.formLayout.setLayout(0, QtWidgets.QFormLayout.LabelRole,
self.verticalLayout)
# I want to pass lat/lng here and after user click show data in
Qwidget below, but i will do that on my own i just need those lat/lng
after every click
self.mapa = QtWidgets.QWidget(self.centralwidget)
self.mapa.setObjectName("mapa")
backend = Backend()
channel = QWebChannel()
channel.registerObject('backend', backend)
self.mapa = QWebEngineView()
self.mapa.page().setWebChannel(channel)
self.mapa.setHtml(maphtml)
point=Point(y,x)
#sql = 'select * from geo'
#df = gpd.GeoDataFrame.from_postgis(sql, self.connection,
geom_col='geometry' )
#def min_dist(point, gpd2):
#df['Dist'] = df.apply(lambda row:
point.distance(row.geometry),axis=1)
#geoseries = df.iloc[gpd2['Dist'].idxmin()]
#return geoseries['IdLink']
#point=Point(self.Backend.lat(),self.Backend.lng())
#self.brojka=min_dist(point,df)
self.formLayout_3 = QtWidgets.QFormLayout(self.mapa)
self.formLayout_3.setObjectName("formLayout_3")
self.formLayout.setWidget(0, QtWidgets.QFormLayout.FieldRole,
self.mapa)
self.graf = QtWidgets.QWidget(self.centralwidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred,
QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(255)
sizePolicy.setHeightForWidth(self.graf.sizePolicy().hasHeightForWidth())
self.graf.setSizePolicy(sizePolicy)
self.graf.setMouseTracking(True)
self.graf.setObjectName("graf")
self.graf = QWebEngineView(self.centralwidget)
self.formLayout_2 = QtWidgets.QFormLayout(self.graf)
self.formLayout_2.setObjectName("formLayout_2")
self.formLayout.setWidget(1, QtWidgets.QFormLayout.SpanningRole,
self.graf)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 978, 21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.gumb_spoji.setText(_translate("MainWindow", "Spoji se na bazu"))
self.pon.setText(_translate("MainWindow", "Ponedjeljak"))
self.uto.setText(_translate("MainWindow", "Utorak"))
self.sri.setText(_translate("MainWindow", "Srijeda"))
self.cet.setText(_translate("MainWindow", "Cetvrtak"))
self.pet.setText(_translate("MainWindow", "Petak"))
self.sub.setText(_translate("MainWindow", "Subota"))
self.ned.setText(_translate("MainWindow", "Nedjelja"))
self.comboBox.setItemText(0, _translate("MainWindow", "5min"))
self.comboBox.setItemText(1, _translate("MainWindow", "15min"))
self.gumb_dohvati.setText(_translate("MainWindow", "Dohvati
podatke"))
self.label.setText(_translate("MainWindow", "Srednja vrijednost"))
self.label_2.setText(_translate("MainWindow", "Median"))
self.label_3.setText(_translate("MainWindow", "Standardna
devijacija"))
if __name__ == "__main__":
import sys
app = QtCore.QCoreApplication.instance()
if app is None:
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
I saw similar questions but couldn't make it work so far... In PyQt4 i have it almost working, but since i am bad at JS, i dont know how to to return lat/lng intead of getCenter().lat from this code: 我看到了类似的问题,但到目前为止还无法解决...在PyQt4中,它几乎可以正常工作,但是由于我对JS不好,所以我不知道如何从getCenter()。lat返回lat / lng intead此代码:
if(typeof MainWindow != 'undefined') { var onMapMove = function(e) { MainWindow.onMapMove(map.getCenter().lat, map.getCenter().lng) }; map.on('click', onMapMove); onMapMove();
I can not work much with your code because it is badly formatted and there are missing elements to define so my answer will be based on showing you an example. 由于您的代码格式不正确,并且缺少定义的元素,因此我不能做很多工作,因此我的答案将基于向您展示一个示例。
First of all it does not put all the code in a file, that makes it difficult to maintain the code, in this case I have divided into the following files: 首先,它不会将所有代码都放在一个文件中,这使得很难维护代码,在这种情况下,我将其分为以下文件:
.
├── index.html
├── main.py
├── utils.css
└── utils.js
window.onload = function() { new QWebChannel(qt.webChannelTransport, function (channel) { window.backend = channel.objects.backend; }); var m = {}; start_(L, 'L'); start_(WE, 'WE'); function start_(API, suffix) { var mapDiv = 'map' + suffix; var map = API.map(mapDiv, { center: [51.505, -0.09], zoom: 4, dragging: true, scrollWheelZoom: true, proxyHost: 'http://srtm.webglearth.com/cgi-bin/corsproxy.fcgi?url=' }); m[suffix] = map; //Add baselayer API.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: '© OpenStreetMap contributors' }).addTo(map); //Add TileJSON overlay var json = { "profile": "mercator", "name": "Grand Canyon USGS", "format": "png", "bounds": [15.976953506469728, 45.813157465613884], "minzoom": 10, "version": "1.0.0", "maxzoom": 16, "center": [15.976953506469728, 45.813157465613884, 16 ], "type": "overlay", "description": "", "basename": "grandcanyon", "tilejson": "2.0.0", "sheme": "xyz", "tiles": ["http://tileserver.maptiler.com/grandcanyon/{z}/{x}/{y}.png"] }; if (API.tileLayerJSON) { var overlay2 = API.tileLayerJSON(json, map); } else { //If not able to display the overlay, at least move to the same location map.setView([json.center[1], json.center[0]], json.center[2]); } //Print coordinates of the mouse map.on('click', function(e) { document.getElementById('coords').innerHTML = e.latlng.lat + ', ' + e.latlng.lng; backend.pointClicked(e.latlng.lat, e.latlng.lng); }); } //Synchronize view m['L'].on('click', function(e) { var center = m['L'].getCenter(); var zoom = m['L'].getZoom(); m['WE'].setView([center['lat'], center['lng']], zoom); }); }
html, body { padding: 0; margin: 0; overflow: hidden; } #mapL, #mapWE { position: absolute !important; top: 0; right: 0; bottom: 0; left: 0; background-color: #fff; position: absolute !important; } #mapL { right: 0%; } #mapWE { left: 100%; } #coords { position: absolute; bottom: 0; }
<!DOCTYPE HTML> <html> <head> <meta name="robots" content="index, all"/> <title>WebGL Earth API - Side-by-side - Basic Leaflet compatibility </title> <link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.2/leaflet.css"/> <link rel="stylesheet" href="utils.css"/> <script src="qrc:///qtwebchannel/qwebchannel.js"></script> <script type="text/javascript" src="http://cdn.leafletjs.com/leaflet-0.7.2/leaflet.js"></script> <script type="text/javascript" src="http://www.webglearth.com/v2/api.js"></script> <script type="text/javascript" src="utils.js"> </script> </head> <body> <div id="mapL"></div> <div id="mapWE"></div> <div id="coords"></div> </body> </html>
main.py main.py
from PyQt5 import QtWebEngineWidgets, QtWidgets, QtCore, QtWebChannel
class Backend(QtCore.QObject):
pointChanged = QtCore.pyqtSignal(float, float)
@QtCore.pyqtSlot(float,float)
def pointClicked(self, x, y):
self.pointChanged.emit(x, y)
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
map_view = QtWebEngineWidgets.QWebEngineView()
backend = Backend(self)
backend.pointChanged.connect(self.onPointChanged)
channel = QtWebChannel.QWebChannel(self)
channel.registerObject('backend', backend)
map_view.page().setWebChannel(channel)
file = QtCore.QDir.current().absoluteFilePath("index.html")
map_view.load(QtCore.QUrl.fromLocalFile(file))
self.setCentralWidget(map_view)
@QtCore.pyqtSlot(float,float)
def onPointChanged(self, x, y):
print("new points")
print(x, y)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.