在qml中用户点击的地方在地图上画圈
Putting a circle on the map where the user clicks in qml
我正在尝试让我的 .qml 地图在用户点击的地方显示一个圆圈,但一直让自己陷入困境。 window 将坐标正确输出到 GeoWidget 中的旋转框,但我希望在该位置出现一个圆圈,以便用户获得一些反馈。
coord_map.qml
import QtQuick 2.0
import QtQuick.Controls 2.0
import QtQuick.Controls.Material 2.0
import QtQuick.Controls.Universal 2.0
import Fluid.Controls 1.0
import QtLocation 5.6
import QtPositioning 5.6
Item {
width: 600
height: 600
Map {
id: map
anchors.fill: parent
zoomLevel: 6
center: (0, 0)
MapItemView {
model: src
delegate: MapQuickItem {
coordinate: src.position.coordinate
anchorPoint.x: image.width * 0.5
anchorPoint.y: image.height
sourceItem: Column {
Image { id: image; source: "marker.png" }
Text { text: title; font.bold: true }
}
}
}
MapCircle {
id: circle
radius: parent.width/10
border.width: 1
color: 'green'
}
}
MouseArea {
id: mouse
anchors.fill: parent
onClicked: {controller.update_from_map(map.toCoordinate(Qt.point(mouse.x, mouse.y)))
circle.center(map.toCoordinate(Qt.point(mouse.x, mouse.y)))
}
plugin: Plugin {
name: "osm"
}
}
}
coordbox.py
import os
import sys
from pathlib import Path
from PySide2.QtCore import Property, Signal, Slot, Qt, QUrl
from PySide2.QtPositioning import QGeoCoordinate
from PySide2.QtQuickWidgets import QQuickWidget
from PySide2.QtWidgets import (
QApplication,
QDialog,
QDialogButtonBox,
QDoubleSpinBox,
QHBoxLayout,
QLabel,
QToolButton,
QVBoxLayout,
QWidget,
QWizard,
QWizardPage,
)
CURRENT_DIRECTORY = Path(__file__).resolve().parent
# TODO: Give the user feedback on where their coordinate is when clicked
class MapDialog(QDialog):
def __init__(self, geo_widget):
super().__init__(geo_widget)
self.setWindowTitle("Map")
self.map_widget = QQuickWidget(resizeMode=QQuickWidget.SizeRootObjectToView)
self.map_widget.rootContext().setContextProperty("controller", geo_widget)
filename = os.fspath(CURRENT_DIRECTORY / "coord_map.qml")
url = QUrl.fromLocalFile(filename)
self.map_widget.setSource(url)
button_box = QDialogButtonBox()
button_box.setOrientation(Qt.Horizontal)
button_box.setStandardButtons(QDialogButtonBox.Cancel | QDialogButtonBox.Ok)
lay = QVBoxLayout(self)
lay.addWidget(self.map_widget)
lay.addWidget(button_box)
button_box.accepted.connect(self.accept)
button_box.rejected.connect(self.reject)
class GeoWidget(QWidget):
coordinate_changed = Signal(name="coordinateChanged")
def __init__(self, parent=None):
super().__init__(parent)
self._coordinate = QGeoCoordinate(0, 0)
self._lat_spinbox = QDoubleSpinBox(
minimum=49.0, maximum=56.0 # , valueChanged=self.handle_value_changed,
)
self._lng_spinbox = QDoubleSpinBox(
minimum=-8, maximum=2 # , valueChanged=self.handle_value_changed,
)
self.btn = QToolButton(text="Map", clicked=self.handle_clicked)
self.map_view = MapDialog(self)
# self.coordinate_changed.connect(self.handle_value_changed)
# self.coordinate_changed.connect(self.handle_value_changed)
lay = QHBoxLayout(self)
lay.addWidget(QLabel("Latitude:"))
lay.addWidget(self._lat_spinbox)
lay.addWidget(QLabel("Longitude:"))
lay.addWidget(self._lng_spinbox)
lay.addWidget(self.btn)
@Property(QGeoCoordinate, notify=coordinate_changed)
def coordinate(self):
return self._coordinate
@coordinate.setter
def coordinate(self, coordinate):
if self.coordinate == coordinate:
return
self._coordinate = coordinate
self.coordinate_changed.emit()
def handle_value_changed(self):
coordinate = QGeoCoordinate(
self._lat_spinbox.value(), self._lng_spinbox.value()
)
self.coordinate = coordinate
@Slot(QGeoCoordinate)
def update_from_map(self, coordinate):
self.coordinate = coordinate
self._lat_spinbox.setValue(self.coordinate.latitude())
self._lng_spinbox.setValue(self.coordinate.longitude())
def handle_clicked(self):
self.map_view.exec_()
# Rest of code is used to debug this coordinate box
class WizardPage(QWizardPage):
def __init__(self, parent=None):
super().__init__(parent)
self.geo_widget1 = GeoWidget()
self.geo_widget2 = GeoWidget()
self.registerField("coordinate1", self.geo_widget1)
self.registerField("coordinate2", self.geo_widget2)
lay = QVBoxLayout(self)
lay.addWidget(self.geo_widget1)
lay.addWidget(self.geo_widget2)
def main():
app = QApplication(sys.argv)
w = QWizard()
page = WizardPage()
w.addPage(page)
w.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
我已经让它工作了,但是它只是显示一个空白屏幕,现在我正在尝试实施反馈。我试图尽可能多地从文档中获取信息,但无法调试 qml 导致了问题,因为我什至不知道 onClicked 是否可以同时做两件事(例如,将坐标发送到旋转框并添加一个反馈圈。
您的代码中有几项未定义,因此我将删除它们。另一方面,center 是一个 属性,它不是一个函数,所以你必须做的是分配位置。还需要注意的是,MapCircle 的半径是以米为单位,而不是以像素为单位,因此您必须为您使用的缩放选择一个合适的值。
import QtLocation 5.6
import QtPositioning 5.6
import QtQuick 2.0
import QtQuick.Controls 2.0
import QtQuick.Controls.Material 2.0
import QtQuick.Controls.Universal 2.0
Item {
width: 600
height: 600
Map {
id: map
anchors.fill: parent
zoomLevel: 6
center: QtPositioning.coordinate(0, 0)
MapCircle {
id: circle
radius: 100000
border.width: 1
color: 'green'
}
MouseArea {
id: mouse
anchors.fill: parent
onClicked: {
var pos = map.toCoordinate(Qt.point(mouse.x, mouse.y));
circle.center = pos;
controller.update_from_map(pos);
}
}
plugin: Plugin {
name: "osm"
}
}
}
我正在尝试让我的 .qml 地图在用户点击的地方显示一个圆圈,但一直让自己陷入困境。 window 将坐标正确输出到 GeoWidget 中的旋转框,但我希望在该位置出现一个圆圈,以便用户获得一些反馈。
coord_map.qml
import QtQuick 2.0
import QtQuick.Controls 2.0
import QtQuick.Controls.Material 2.0
import QtQuick.Controls.Universal 2.0
import Fluid.Controls 1.0
import QtLocation 5.6
import QtPositioning 5.6
Item {
width: 600
height: 600
Map {
id: map
anchors.fill: parent
zoomLevel: 6
center: (0, 0)
MapItemView {
model: src
delegate: MapQuickItem {
coordinate: src.position.coordinate
anchorPoint.x: image.width * 0.5
anchorPoint.y: image.height
sourceItem: Column {
Image { id: image; source: "marker.png" }
Text { text: title; font.bold: true }
}
}
}
MapCircle {
id: circle
radius: parent.width/10
border.width: 1
color: 'green'
}
}
MouseArea {
id: mouse
anchors.fill: parent
onClicked: {controller.update_from_map(map.toCoordinate(Qt.point(mouse.x, mouse.y)))
circle.center(map.toCoordinate(Qt.point(mouse.x, mouse.y)))
}
plugin: Plugin {
name: "osm"
}
}
}
coordbox.py
import os
import sys
from pathlib import Path
from PySide2.QtCore import Property, Signal, Slot, Qt, QUrl
from PySide2.QtPositioning import QGeoCoordinate
from PySide2.QtQuickWidgets import QQuickWidget
from PySide2.QtWidgets import (
QApplication,
QDialog,
QDialogButtonBox,
QDoubleSpinBox,
QHBoxLayout,
QLabel,
QToolButton,
QVBoxLayout,
QWidget,
QWizard,
QWizardPage,
)
CURRENT_DIRECTORY = Path(__file__).resolve().parent
# TODO: Give the user feedback on where their coordinate is when clicked
class MapDialog(QDialog):
def __init__(self, geo_widget):
super().__init__(geo_widget)
self.setWindowTitle("Map")
self.map_widget = QQuickWidget(resizeMode=QQuickWidget.SizeRootObjectToView)
self.map_widget.rootContext().setContextProperty("controller", geo_widget)
filename = os.fspath(CURRENT_DIRECTORY / "coord_map.qml")
url = QUrl.fromLocalFile(filename)
self.map_widget.setSource(url)
button_box = QDialogButtonBox()
button_box.setOrientation(Qt.Horizontal)
button_box.setStandardButtons(QDialogButtonBox.Cancel | QDialogButtonBox.Ok)
lay = QVBoxLayout(self)
lay.addWidget(self.map_widget)
lay.addWidget(button_box)
button_box.accepted.connect(self.accept)
button_box.rejected.connect(self.reject)
class GeoWidget(QWidget):
coordinate_changed = Signal(name="coordinateChanged")
def __init__(self, parent=None):
super().__init__(parent)
self._coordinate = QGeoCoordinate(0, 0)
self._lat_spinbox = QDoubleSpinBox(
minimum=49.0, maximum=56.0 # , valueChanged=self.handle_value_changed,
)
self._lng_spinbox = QDoubleSpinBox(
minimum=-8, maximum=2 # , valueChanged=self.handle_value_changed,
)
self.btn = QToolButton(text="Map", clicked=self.handle_clicked)
self.map_view = MapDialog(self)
# self.coordinate_changed.connect(self.handle_value_changed)
# self.coordinate_changed.connect(self.handle_value_changed)
lay = QHBoxLayout(self)
lay.addWidget(QLabel("Latitude:"))
lay.addWidget(self._lat_spinbox)
lay.addWidget(QLabel("Longitude:"))
lay.addWidget(self._lng_spinbox)
lay.addWidget(self.btn)
@Property(QGeoCoordinate, notify=coordinate_changed)
def coordinate(self):
return self._coordinate
@coordinate.setter
def coordinate(self, coordinate):
if self.coordinate == coordinate:
return
self._coordinate = coordinate
self.coordinate_changed.emit()
def handle_value_changed(self):
coordinate = QGeoCoordinate(
self._lat_spinbox.value(), self._lng_spinbox.value()
)
self.coordinate = coordinate
@Slot(QGeoCoordinate)
def update_from_map(self, coordinate):
self.coordinate = coordinate
self._lat_spinbox.setValue(self.coordinate.latitude())
self._lng_spinbox.setValue(self.coordinate.longitude())
def handle_clicked(self):
self.map_view.exec_()
# Rest of code is used to debug this coordinate box
class WizardPage(QWizardPage):
def __init__(self, parent=None):
super().__init__(parent)
self.geo_widget1 = GeoWidget()
self.geo_widget2 = GeoWidget()
self.registerField("coordinate1", self.geo_widget1)
self.registerField("coordinate2", self.geo_widget2)
lay = QVBoxLayout(self)
lay.addWidget(self.geo_widget1)
lay.addWidget(self.geo_widget2)
def main():
app = QApplication(sys.argv)
w = QWizard()
page = WizardPage()
w.addPage(page)
w.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
我已经让它工作了,但是它只是显示一个空白屏幕,现在我正在尝试实施反馈。我试图尽可能多地从文档中获取信息,但无法调试 qml 导致了问题,因为我什至不知道 onClicked 是否可以同时做两件事(例如,将坐标发送到旋转框并添加一个反馈圈。
您的代码中有几项未定义,因此我将删除它们。另一方面,center 是一个 属性,它不是一个函数,所以你必须做的是分配位置。还需要注意的是,MapCircle 的半径是以米为单位,而不是以像素为单位,因此您必须为您使用的缩放选择一个合适的值。
import QtLocation 5.6
import QtPositioning 5.6
import QtQuick 2.0
import QtQuick.Controls 2.0
import QtQuick.Controls.Material 2.0
import QtQuick.Controls.Universal 2.0
Item {
width: 600
height: 600
Map {
id: map
anchors.fill: parent
zoomLevel: 6
center: QtPositioning.coordinate(0, 0)
MapCircle {
id: circle
radius: 100000
border.width: 1
color: 'green'
}
MouseArea {
id: mouse
anchors.fill: parent
onClicked: {
var pos = map.toCoordinate(Qt.point(mouse.x, mouse.y));
circle.center = pos;
controller.update_from_map(pos);
}
}
plugin: Plugin {
name: "osm"
}
}
}