【问题标题】:Is it possible to create MapQuickItems from qml in python?是否可以在 python 中从 qml 创建 MapQuickItems?
【发布时间】:2018-03-07 20:59:48
【问题描述】:

我正在开发 PyQt5Qml 应用程序。该应用程序显示 2 QLineEdits、2 QPushButton 和我的Qml 提供的地图。该应用程序的功能之一是通过带有标题和坐标的XML-List 解析(在python 中),并在地图上的坐标上添加图钉。我现在的问题是它只显示最后一个坐标。我意识到这是因为我只更改了 Qml 中 pin Item 的属性,而不是创建新的。我现在的问题是:是否可以在 python 中创建MapQuickItems

【问题讨论】:

  • 我知道这个问题有点奇怪,但我是 Qml 的新手,我真的不知道如何更好地解释我的问题。
  • 我的问题是,为什么你会想要这样做,当你可能会从你在 Python 中定义并暴露给 QML 的模型在 QML 中创建它们时。
  • 这是因为我想在地图上添加多个图钉,为此我需要创建新图钉,而不仅仅是更改一个模型的属性。(您是这个意思吗?)
  • 是的,我就是这个意思。您使用一个模型,该模型包含任意数量的引脚的属性。从该模型中,您可以在 QML 中实例化引脚。我不知道 Map API 也没有在此处安装它,但我很确定您的 MapQuickItem 继承了 QQuickItem 或至少 QObject 这意味着您可以将它们用作 @987654334 中的委托@ 或 Instantiator 为模型中的每个条目实例化其中一个。

标签: python python-3.x pyqt qml pyqt5


【解决方案1】:

正如我在@derM 评论的那样,您只需创建一个模型并将其公开给您的 QML,PyQt 没有文档,但我们可以参考 C++ 文档,因为概念相似。作为一个示例,我在以下模型中创建了包含标记信息的模型,在这种情况下考虑标记的位置和颜色。

class MarkerItem(object):
    def __init__(self, position, color=QColor("red")):
        self._position = position
        self._color = color

    def position(self):
        return self._position

    def setPosition(self, value):
        self._position = value

    def color(self):
        return self._color

    def setColor(self, value):
        self._color = value


class MarkerModel(QAbstractListModel):
    PositionRole = Qt.UserRole + 1
    ColorRole = Qt.UserRole + 2

    _roles = {PositionRole: QByteArray(b"markerPosition"), ColorRole: QByteArray(b"markerColor")}

    def __init__(self, parent=None):
        QAbstractListModel.__init__(self, parent)
        self._markers = []

    def rowCount(self, index=QModelIndex()):
        return len(self._markers)

    def roleNames(self):
        return self._roles

    def data(self, index, role=Qt.DisplayRole):
        if index.row() >= self.rowCount():
            return QVariant()
        marker = self._markers[index.row()]

        if role == MarkerModel.PositionRole:
            return marker.position()

        elif role == MarkerModel.ColorRole:
            return marker.color()

        return QVariant()

    def setData(self, index, value, role=Qt.EditRole):
        if index.isValid():
            marker = self._markers[index.row()]
            if role == MarkerModel.PositionRole:
                marker.setPosition(value)

            if role == MarkerModel.ColorRole:
                marker.setColor(value)

            self.dataChanged.emit(index, index)
            return True
        return QAbstractListModel.setData(self, index, value, role)

    def addMarker(self, marker):
        self.beginInsertRows(QModelIndex(), self.rowCount(), self.rowCount())
        self._markers.append(marker)
        self.endInsertRows()

    def flags(self, index):
        if not index.isValid():
            return Qt.ItemIsEnabled
        return QAbstractListModel.flags(index)|Qt.ItemIsEditable

    def moveRandom(self, ix):
        ind = self.index(ix, 0)
        current_pos = self.data(ind, MarkerModel.PositionRole)
        next_pos = current_pos + 0.002*QPointF(random() - 0.5, random() - 0.5)
        self.setData(ind, next_pos, MarkerModel.PositionRole)
        self.setData(ind, QColor(randint(0, 255), randint(0, 255), randint(0, 255)), MarkerModel.ColorRole)

然后用在下面的例子中:

ma​​in.py

if __name__ == "__main__":
    import sys

    QCoreApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
    app = QGuiApplication(sys.argv)
    engine = QQmlApplicationEngine()

    model = MarkerModel()
    model.addMarker(MarkerItem(QPointF(-12.0464, -77.0428), QColor("black")))
    model.addMarker(MarkerItem(QPointF(-12.0340, -77.0428), QColor("red")))

    model.addMarker(MarkerItem(QPointF(-12.0440, -77.0280), QColor("#9f5522")))

    context = engine.rootContext()
    context.setContextProperty('markerModel', model)

    engine.load(QUrl.fromLocalFile("main.qml"))

    if len(engine.rootObjects()) == 0:
        sys.exit(-1)

    engine.quit.connect(app.quit)

    timer = QTimer(engine)
    timer.timeout.connect(lambda: model.moveRandom(0))
    timer.start(100)

    sys.exit(app.exec_())

ma​​in.qml

import QtQuick 2.0
import QtQuick.Window 2.0
import QtLocation 5.5
import QtPositioning 5.5

Window {
    visible: true
    title: "Python OSM"
    width: 640
    height: 480
    property int marker_size: 16

    Map {
        id: map
        anchors.fill: parent
        plugin: Plugin {
            name: "osm"
        }
        center: QtPositioning.coordinate(-12.0464, -77.0428)
        zoomLevel: 14

        MapItemView {
            model: markerModel
            delegate: MapQuickItem{
                anchorPoint: Qt.point(2.5, 2.5)
                coordinate: QtPositioning.coordinate(markerPosition.x, markerPosition.y)
                zoomLevel: 0
                sourceItem: Rectangle{
                    width:  marker_size
                    height: marker_size
                    radius: marker_size/2
                    border.color: "white"
                    color: markerColor
                    border.width: 1
                }
            }
        }
    }
}

获取如下图所示:

注意:我添加了 moveRandom 方法来向您展示如何更新标记的位置,正如您在执行示例时将看到标记随机移动的那样

完整的例子可以看下面link

【讨论】:

  • 非常感谢!!这对我帮助很大。
猜你喜欢
  • 1970-01-01
  • 2018-03-20
  • 2022-11-08
  • 1970-01-01
  • 2018-12-11
  • 2014-04-16
  • 2012-11-18
  • 2010-10-13
相关资源
最近更新 更多