python - 单击按钮后刷新 QML 文件中的 QQuickWidget

标签 python python-3.x pyqt qml pyqt5

使用 QQuickWidget 和 qml 文件创建了一个 MapWidget,以放大给定的位置坐标。但是,只要坐标发生变化, map 就不会刷新。我正在尝试连接一个可以单击以更新 map 的按钮,但到目前为止还没有运气。有没有办法获取按钮的 id 并将其传递到 qml 文件,以便在坐标更改时更新或刷新 map ?

main.py

class MapWidget(QtQuickWidgets.QQuickWidget):
    def __init__(self, parent=None):
        super(MapWidget, self).__init__(parent,
            resizeMode=QtQuickWidgets.QQuickWidget.SizeRootObjectToView)
        model = MarkerModel(self)
        self.rootContext().setContextProperty("markermodel", model)
        self.rootContext().setContextProperty("lataddr", globals.latitude)
        self.rootContext().setContextProperty("lonaddr", globals.longitude)
        qml_path = os.path.join(os.path.dirname(__file__), "main.qml")
        self.setSource(QtCore.QUrl.fromLocalFile(qml_path))

        positions = [(globals.latitude, globals.longitude)]
        urls = ["http://maps.gstatic.com/mapfiles/ridefinder-images/mm_20_red.png"]


        for c, u in zip(positions, urls):
            coord = QtPositioning.QGeoCoordinate(*c)
            source = QtCore.QUrl(u)
            model.appendMarker({"position": coord , "source": source})



class project_ui(QWidget):
    def setup(self, window):
        "omitted code"
        self.btn = QPushButton('Search', self)
        self.btn.setFixedWidth(200)
        self.btn.clicked.connect("reload map in qml file")

main.qml

Rectangle {
     id:rectangle
     width: 640
     height: 480
     Plugin {
    id: osmPlugin
    name: "osm"
}
property variant locationTC: QtPositioning.coordinate(lataddr, lonaddr)

Map {
    id: map
    anchors.fill: parent
    plugin: osmPlugin
    center: locationTC
    zoomLevel: 10
    }
    MapItemView{
        model: markermodel
        delegate: MapQuickItem {
            coordinate: position_marker
            anchorPoint.x: image.width
            anchorPoint.y: image.height
            sourceItem:
                Image { id: image; source: source_marker }
        }
    }
}

最佳答案

考虑到您只想移动一个标记,您必须创建一个将位置作为 q 属性的 QObject,导出该对象并在 QML 中进行绑定(bind)。

ma​​in.py

import os
from PyQt5 import QtCore, QtGui, QtWidgets, QtQuickWidgets, QtPositioning

class MarkerObject(QtCore.QObject):
    coordinateChanged = QtCore.pyqtSignal(QtPositioning.QGeoCoordinate)
    sourceChanged = QtCore.pyqtSignal(QtCore.QUrl)

    def __init__(self, parent=None):
        super(MarkerObject, self).__init__(parent)
        self._coordinate = QtPositioning.QGeoCoordinate()
        self._source = QtCore.QUrl()

    def getCoordinate(self):
        return self._coordinate

    def setCoordinate(self, coordinate):
        if self._coordinate != coordinate:
            self._coordinate = coordinate
            self.coordinateChanged.emit(self._coordinate)

    def getSource(self):
        return self._source

    def setSource(self, source):
        if self._source != source:
            self._source = source
            self.sourceChanged.emit(self._source)

    coordinate = QtCore.pyqtProperty(QtPositioning.QGeoCoordinate, fget=getCoordinate, fset=setCoordinate, notify=coordinateChanged)
    source = QtCore.pyqtProperty(QtCore.QUrl, fget=getSource, fset=setSource, notify=sourceChanged)

class MapWidget(QtQuickWidgets.QQuickWidget):
    def __init__(self, parent=None):
        super(MapWidget, self).__init__(parent,
            resizeMode=QtQuickWidgets.QQuickWidget.SizeRootObjectToView)
        self._marker_object = MarkerObject(parent)
        self._marker_object.setSource(QtCore.QUrl("http://maps.gstatic.com/mapfiles/ridefinder-images/mm_20_red.png"))
        self.rootContext().setContextProperty("marker_object", self._marker_object)
        qml_path = os.path.join(os.path.dirname(__file__), "main.qml")
        self.setSource(QtCore.QUrl.fromLocalFile(qml_path))

    @QtCore.pyqtSlot(QtPositioning.QGeoCoordinate)
    def moveMarker(self, pos):
        self._marker_object.setCoordinate(pos)

class Widget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Widget, self).__init__(parent)
        self._lat_spinbox = QtWidgets.QDoubleSpinBox(
            minimum=-90, 
            maximum=90, 
            decimals=6, 
            value=59.91
        )
        self._lng_spinbox = QtWidgets.QDoubleSpinBox(
            minimum=-180, 
            maximum=180, 
            decimals=6, 
            value=10.75
        )
        search_button = QtWidgets.QPushButton("Search", clicked=self.search)
        self._map_widget = MapWidget()
        flay = QtWidgets.QFormLayout(self)
        flay.addRow("Latitude:", self._lat_spinbox)
        flay.addRow("Longitude:", self._lng_spinbox)
        flay.addRow(search_button)
        flay.addRow(self._map_widget)
        self.search()

    @QtCore.pyqtSlot()
    def search(self):
        lat = self._lat_spinbox.value()
        lng = self._lng_spinbox.value()
        self._map_widget.moveMarker(QtPositioning.QGeoCoordinate(lat, lng))

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    w = Widget()
    w.show()
    sys.exit(app.exec_())

ma​​in.qml

import QtQuick 2.9
import QtLocation 5.12
import QtPositioning 5.12

Rectangle {
    id:rectangle
    width: 640
    height: 480
    Plugin {
        id: osmPlugin
        name: "osm"
    }
    Map {
        id: map
        anchors.fill: parent
        plugin: osmPlugin
        center: marker_object.coordinate
        zoomLevel: 10

        MapQuickItem {
        coordinate: marker_object.coordinate
        anchorPoint.x: image.width
        anchorPoint.y: image.height
            sourceItem: Image {
                id: image
                source: marker_object.source
            }
        }
    }
}

enter image description here

关于python - 单击按钮后刷新 QML 文件中的 QQuickWidget,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54770913/

相关文章:

python - pyqt;服务器重启后QTcpSocket始终处于connectingState状态;

python - PyQt5 QWidget.setGeometry() 不适用于 QLabel

python - PyQt 进度条用线程更新

python - 如何在 python-3 中导入 urlparse?

python - 从十六进制到有符号整数的转换不起作用

python - 如何在 Python 中使用 "map"函数? (如何重写 for 循环?)

python - 损坏的 DAG : No module named 'airflow.contrib.gsc_to_gcs'

python - 查询没有命名直通字段的多对多关系

python - 使用 Pandas 将数据框中的多列转换为两个新列

python-3.x - 是否可以使用 api 将数据帧保存到 atlassian 页面?