我有个小问题让我花了一大早的时间。我正试图根据pyQt使用Geocoder传入的本地坐标绘制QML格式的地图屏幕。我可以画出地图,但信号发出后,地图似乎不会更新。我对QML和signals/slots比较陌生。任何帮助都是值得感激的。
主.py

from PyQt5.QtGui import QGuiApplication
from PyQt5.QtQml import QQmlApplicationEngine
from PyQt5.QtCore import QObject, pyqtSignal, pyqtSlot

class Point(QObject):
    def __init__(self, lat, lng):
        QObject.__init__(self)
        self.lat = lat
        self.lng = lng


    #Signal sending point
    #Give the name of the argument through arguments=['lat', 'lng']
    #Otherwise, it will not be possible to get it in QML
    showCenter = pyqtSignal(float, float, arguments=['lat', 'lng'])

    #Slot for emitting point
    @pyqtSlot()
    def emitPoint(self):
        self.showCenter.emit(self.lat, self.lng)


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

    #Create an instance of the application
    app = QGuiApplication(sys.argv)

    #Create a QML engine
    engine = QQmlApplicationEngine()

    #Create a Point object
    g = geocoder.ip('me')
    center_point = Point(g.latlng[0], g.latlng[1])

    #And register it in the context of QML
    engine.rootContext().setContextProperty("center_point", center_point)

    #Load the qml file into the engine
    engine.load("main.qml")

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

主.qml
import QtQuick 2.5
import QtQml 2.0
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.2
import QtPositioning 5.9
import QtLocation 5.9

ApplicationWindow {
    visible: true
    width: 640
    height: 480
    title: qsTr("Map Point demo")
    color: "whitesmoke"

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

    Map {
        id: map
        anchors.fill: parent
        plugin: mapPlugin
        center: QtPositioning.coordinate(0.0, 0.0)
        zoomLevel: 6

        MapCircle {
            id: dot
            center: QtPositioning.coordinate(0.0, 0.0)
            radius: 50
            color: 'red'
        }

        Connections {
            target: center_point

            onEmitPoint: {
                console.info("Point changed")
                map.center = QtPositioning.coordinate(lat, lng)
                dot.center = QtPositioning.coordinate(lat, lng)
            }
        }
    }

    Component.onCompleted: {
        console.info("Signal Emitted")
        center_point.emitPoint()
    }
}

最佳答案

当您使用连接时,如果目标信号被称为name_of_signal,则必须使用onName_of_signal,如果您的情况是showCenter,则必须使用onShowCenter

Connections {
    target: center_point

    onShowCenter: { // <---
        console.info("Point changed")
        map.center = QtPositioning.coordinate(lat, lng)
        dot.center = QtPositioning.coordinate(lat, lng)
    }
}

另一个选项是创建一个qproperty,当您在another answer中使用它时,它可以很容易地在QML中使用:
主.py
from PyQt5 import QtCore, QtGui, QtPositioning, QtQml

class PointObject(QtCore.QObject):
    coordinateChanged = QtCore.pyqtSignal(QtPositioning.QGeoCoordinate)

    def __init__(self, parent=None):
        super(PointObject, self).__init__(parent)
        self._coordinate = QtPositioning.QGeoCoordinate()

    def getCoordinate(self):
        return self._coordinate

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

    coordinate = QtCore.pyqtProperty(QtPositioning.QGeoCoordinate, fget=getCoordinate, fset=setCoordinate, notify=coordinateChanged)

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

    #Create an instance of the application
    app = QtGui.QGuiApplication(sys.argv)
    #Create a QML engine
    engine = QtQml.QQmlApplicationEngine()
    #Create a Point object
    g = geocoder.ip('me')
    center_point = PointObject()
    center_point.setCoordinate(QtPositioning.QGeoCoordinate(*g.latlng))
    #And register it in the context of QML
    engine.rootContext().setContextProperty("center_point", center_point)
    #Load the qml file into the engine
    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)
    engine.quit.connect(app.quit)
    sys.exit(app.exec_())

主.qml
import QtQuick 2.5
import QtQml 2.0
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.2
import QtPositioning 5.9
import QtLocation 5.9

ApplicationWindow {
    visible: true
    width: 640
    height: 480
    title: qsTr("Map Point demo")
    color: "whitesmoke"

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

    Map {
        id: map
        anchors.fill: parent
        plugin: mapPlugin
        center: center_point.coordinate
        zoomLevel: 6

        MapCircle {
            id: dot
            center: center_point.coordinate
            radius: 50
            color: 'red'
        }
    }
}

关于python - QML AppWindow信号发出后未更新,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/55026336/

10-16 11:55