在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"
        }

    }

}