gpt4 book ai didi

python - 无法通过 MouseClick 将 MapCircles 添加到 QML map

转载 作者:行者123 更新时间:2023-12-01 08:10:23 25 4
gpt4 key购买 nike

我正在尝试创建一些将在 QML map 上动态移动的标记。然而,在此之前,我需要使用鼠标将它们全部绘制在 map 上,以便稍后更新它们。我一直在使用 pyqtProperty 将我需要的坐标发送到 QML,但是当我尝试将它们添加到 MapItemView 时,它们是未定义的。下面的代码演示了我希望实现的目标。问题是我从另一个 python 对象传递 pyqtProperty 到 QML,而该对象没有像 main.py 中那样使用 setContextProperty() 添加吗?或者我是否错误地使用了 MapItemView 委托(delegate)?

ma​​in.qml

import QtQuick 2.7
import QtQml 2.5
import QtQuick.Controls 1.3
import QtQuick.Controls.Styles 1.3
import QtQuick.Window 2.2
import QtQuick.Layouts 1.2
import QtPositioning 5.9
import QtLocation 5.3
import QtQuick.Dialogs 1.1

ApplicationWindow {
id: root
width: 640
height: 480
visible: true

ListModel {
id: markers
}

Plugin {
id: mapPlugin
name: "osm" //"mapboxgl" "osm" "esri"
}

Map {
id: map
anchors.fill: parent
plugin: mapPlugin
center: atc.location
zoomLevel: 14

MapItemView {
model: markers
delegate: MapCircle {
radius: 50
color: 'red'
center: markLocation //issue here?
}
}

MapCircle {
id: home
center: atc.location
radius: 40
color: 'white'
}

MouseArea {
id: mousearea
anchors.fill: map
acceptedButtons: Qt.LeftButton | Qt.RightButton
hoverEnabled: true
property var coord: map.toCoordinate(Qt.point(mouseX, mouseY))

onDoubleClicked: {
if (mouse.button === Qt.LeftButton)
{
//Capture information for model here
atc.plot_mark(
"marker",
mousearea.coord.latitude,
mousearea.coord.longitude)
markers.append({
name: "markers",
markLocation: atc.get_marker_center("markers")
})
}
}
}
}
}

atc.py

import geocoder
from DC import DC
from PyQt5.QtPositioning import QGeoCoordinate
from PyQt5.QtCore import QObject, pyqtSignal, pyqtProperty, pyqtSlot

class ATC(QObject):
#pyqt Signals
locationChanged = pyqtSignal(QGeoCoordinate)

def __init__(self, parent=None):
super().__init__(parent)
self._location = QGeoCoordinate()
self.dcs = {}
g = geocoder.ip('me')
self.set_location(QGeoCoordinate(*g.latlng))


def set_location(self, coordinate):
if self._location != coordinate:
self._location = coordinate
self.locationChanged.emit(self._location)


def get_location(self):
return self._location


#pyqt Property
location = pyqtProperty(QGeoCoordinate,
fget=get_location,
fset=set_location,
notify=locationChanged)


@pyqtSlot(str, str, str)
def plot_mark(self, mark_name, lat, lng):
dc = DC(mark_name)
self.dcs[mark_name] = dc
self.dcs[mark_name].set_location(
QGeoCoordinate(float(lat), float(lng)))


@pyqtSlot(str)
def get_marker_center(self, mark_name):
return self.dcs[mark_name].location

DC.py

from PyQt5.QtPositioning import QGeoCoordinate
from PyQt5.QtCore import QObject, pyqtSignal, pyqtProperty, pyqtSlot

class DC(QObject):
#pyqt Signals
locationChanged = pyqtSignal(QGeoCoordinate)

def __init__(self, name, parent=None):
super().__init__(parent)
self.name = name
self._location = QGeoCoordinate()


def set_location(self, coordinate):
if self._location != coordinate:
self._location = coordinate
self.locationChanged.emit(self._location)


def get_location(self):
return self._location


#pyqt Property
location = pyqtProperty(QGeoCoordinate,
fget=get_location,
fset=set_location,
notify=locationChanged)

ma​​in.py

from PyQt5.QtGui import QGuiApplication
from PyQt5.QtQml import QQmlApplicationEngine
from PyQt5.QtCore import QObject, QUrl, pyqtSignal, pyqtProperty
from PyQt5.QtPositioning import QGeoCoordinate

from ATC import ATC

if __name__ == "__main__":
import os
import sys

app = QGuiApplication(sys.argv)

engine = QQmlApplicationEngine()

atc = ATC()

engine.rootContext().setContextProperty("atc", atc)

qml_path = os.path.join(os.path.dirname(__file__), "main.qml")
engine.load(QUrl.fromLocalFile(qml_path))

if not engine.rootObjects():
sys.exit(-1)

engine.quit.connect(app.quit)
sys.exit(app.exec_())

最佳答案

您必须在 python 中创建模型,而不是在 QML 中创建模型,以便能够直接处理它,您必须从 QAbstractListModel 继承。为了平滑移动,您应该使用 QxxxAnimation 作为 QPropertyAnimation。

在下面的示例中,每次插入标记时,都会调用 on_markersInserted 函数,该函数会将标记移向窗口的中心。

ma​​in.py

from functools import partial
from PyQt5 import QtCore, QtGui, QtQml, QtPositioning
import geocoder

class Marker(QtCore.QObject):
locationChanged = QtCore.pyqtSignal(QtPositioning.QGeoCoordinate)

def __init__(self, location=QtPositioning.QGeoCoordinate(), parent=None):
super().__init__(parent)
self._location = location

def set_location(self, coordinate):
if self._location != coordinate:
self._location = coordinate
self.locationChanged.emit(self._location)

def get_location(self):
return self._location

location = QtCore.pyqtProperty(QtPositioning.QGeoCoordinate,
fget=get_location,
fset=set_location,
notify=locationChanged)

def move(self, location, duration=1000):
animation = QtCore.QPropertyAnimation(
targetObject=self,
propertyName=b'location',
startValue=self.get_location(),
endValue=location,
duration=duration,
parent=self
)
animation.start(QtCore.QAbstractAnimation.DeleteWhenStopped)

def moveFromTo(self, start, end, duration=1000):
self.set_location(start)
self.move(end, duration)

class MarkerModel(QtCore.QAbstractListModel):
markersInserted = QtCore.pyqtSignal(list)

PositionRole = QtCore.Qt.UserRole + 1000

def __init__(self, parent=None):
super().__init__(parent)
self._markers = []
self.rowsInserted.connect(self.on_rowsInserted)

def rowCount(self, parent=QtCore.QModelIndex()):
return 0 if parent.isValid() else len(self._markers)

def data(self, index, role=QtCore.Qt.DisplayRole):
if index.isValid() and 0 <= index.row() < self.rowCount():
if role == MarkerModel.PositionRole:
return self._markers[index.row()].get_location()
return QtCore.QVariant()

def roleNames(self):
roles = {}
roles[MarkerModel.PositionRole] = b'position'
return roles

@QtCore.pyqtSlot(QtPositioning.QGeoCoordinate)
def appendMarker(self, coordinate):
self.beginInsertRows(QtCore.QModelIndex(), self.rowCount(), self.rowCount())
marker = Marker(coordinate)
self._markers.append(marker)
self.endInsertRows()
marker.locationChanged.connect(self.update_model)

def update_model(self):
marker = self.sender()
try:
row = self._markers.index(marker)
ix = self.index(row)
self.dataChanged.emit(ix, ix, (MarkerModel.PositionRole,))
except ValueError as e:
pass

@QtCore.pyqtSlot(QtCore.QModelIndex, int, int)
def on_rowsInserted(self, parent, first, end):
markers = []
for row in range(first, end+1):
markers.append(self.get_marker(row))
self.markersInserted.emit(markers)


def get_marker(self, row):
if 0 <= row < self.rowCount():
return self._markers[row]

class ManagerMarkers(QtCore.QObject):
locationChanged = QtCore.pyqtSignal(QtPositioning.QGeoCoordinate)

def __init__(self, parent=None):
super().__init__(parent)
self._center= Marker(parent=self)
self._model = MarkerModel(self)
g = geocoder.ip('me')
self.moveCenter(QtPositioning.QGeoCoordinate(*g.latlng))

def model(self):
return self._model

def center(self):
return self._center

def moveCenter(self, position):
self._center.set_location(position)

center = QtCore.pyqtProperty(QtCore.QObject, fget=center, constant=True)
model = QtCore.pyqtProperty(QtCore.QObject, fget=model, constant=True)


# testing
# When a marker is added
# it will begin to move toward
# the center of the window
def on_markersInserted(manager, markers):
end = manager.center.get_location()
for marker in markers:
marker.move(end, 5*1000)

if __name__ == "__main__":
import os
import sys

app = QtGui.QGuiApplication(sys.argv)
manager = ManagerMarkers()
engine = QtQml.QQmlApplicationEngine()
engine.rootContext().setContextProperty("manager", manager)
qml_path = os.path.join(os.path.dirname(__file__), "main.qml")
engine.load(QtCore.QUrl.fromLocalFile(qml_path))
if not engine.rootObjects():
sys.exit(-1)
manager.model.markersInserted.connect(partial(on_markersInserted, manager))
engine.quit.connect(app.quit)
sys.exit(app.exec_())

ma​​in.qml

import QtQuick 2.7
import QtQuick.Controls 2.2
import QtPositioning 5.9
import QtLocation 5.3

ApplicationWindow {
id: root
width: 640
height: 480
visible: true

Plugin {
id: mapPlugin
name: "osm" // "mapboxgl" "osm" "esri"
}

Map {
id: map
anchors.fill: parent
plugin: mapPlugin
center: manager.center.location
zoomLevel: 14

MapCircle {
id: home
center: manager.center.location
radius: 40
color: 'white'
}

MapItemView {
model: manager.model
delegate: MapCircle {
radius: 50
color: 'red'
center: model.position
}
}

MouseArea {
id: mousearea
anchors.fill: map
acceptedButtons: Qt.LeftButton | Qt.RightButton
onDoubleClicked: if (mouse.button === Qt.LeftButton)
manager.model.appendMarker(map.toCoordinate(Qt.point(mouseX, mouseY)))
}
}
}

关于python - 无法通过 MouseClick 将 MapCircles 添加到 QML map ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55290279/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com