Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PyQt5 QML Signal to Python Slot?

Tags:

qt

pyqt

qml

pyqt5

How can a python method/slot be connected to a QML signal? It looks like QtObject.connect() used to work in PyQt4 but it's no longer available in PyQt5.

#Sample QML File (stack.qml)

import QtQuick 2.0

Rectangle {
    MouseArea {
        anchors.fill: parent
        onClicked: {
           // relay this to python
        }
    }
}

--

#Sample Python File
from PyQt5.QtCore import QUrl
from PyQt5.QtGui import QGuiApplication
from PyQt5.QtQuick import QQuickView

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

    app = QGuiApplication(sys.argv)

    view = QQuickView()
    view.setWidth(500)
    view.setHeight(500)
    view.setTitle('Hello PyQt')
    view.setResizeMode(QQuickView.SizeRootObjectToView)
    view.setSource(QUrl.fromLocalFile(os.path.join(os.path.dirname(__file__),'stack.qml')))

    def on_qml_mouse_clicked(mouse_event):
        print 'mouse clicked'

    view.show()
    qml_rectangle = view.rootObject()

    # this technique doesn't work #############################
    qml_rectangle.mousePressEvent.connect(on_qml_mouse_clicked)

    sys.exit(app.exec_())

Some of the PyQT examples pass an object into the QML context via "setContextProperty" and then relay QML events to slots on that object but that approach seems roundabout. Is there a better way?

like image 738
berg Avatar asked Oct 02 '13 06:10

berg


1 Answers

qml_rectangle.mousePressEvent is not a signal, it's an event handler that is called on mouse events, so you can't connect to it. You could just replace it with your handler function (qml_rectangle.mousePressEvent = on_qml_mouse_clicked), but that's not a very clean way of working with Qt.

The better way would be to define a signal in your qml file and emit it from the rectangle's onClicked handler:

import QtQuick 2.0

Rectangle {
    signal clicked()
    MouseArea {
        anchors.fill: parent
        onClicked: {
           parent.clicked()  // emit the parent's signal
        }
    }
}

Then you can just connect to it from your python code:

...
def on_qml_mouse_clicked():
    print('mouse clicked')

qml_rectangle.clicked.connect(on_qml_mouse_clicked)
...
like image 118
mata Avatar answered Sep 23 '22 01:09

mata