QML AppWindow信号发出后未更新

时间:2019-03-06 15:12:08

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

我有一个小问题,使我大部分时间都在花钱。我正在尝试根据pyQt使用Geocoder传递的本地坐标在QML中绘制地图屏幕。我可以将地图绘制好,但是一旦发出信号,它似乎就不会更新。我对QML和信号/插槽比较陌生。任何帮助都表示赞赏。

main.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_())

main.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()
    }
}

1 个答案:

答案 0 :(得分:1)

在使用Connections时,如果目标信号称为name_of_signal,则必须使用onName_of_signa l,在这种情况下,信号是showCenter,因此必须使用onShowCenter

Connections {
    target: center_point

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

另一种选择是创建一个可以在another answer中使用的qproperty,它可以在QML中轻松使用:

main.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_())

main.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'
        }
    }    
}