PyQt5 QML Signal to Python slot?

How can I connect a python method / slot to a QML signal? It seems that QtObject.connect () is used to work in PyQt4, but is 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 PyQT examples pass an object into a QML context through "setContextProperty" and then pass QML events to slots on that object, but this approach seems circular. Is there a better way?

+8
qt pyqt5 pyqt qml
source share
2 answers

qml_rectangle.mousePressEvent not a signal, it is an event handler called by mouse events, so you cannot connect to it. You can simply replace it with a handler function ( qml_rectangle.mousePressEvent = on_qml_mouse_clicked ), but this is not a very clean way to work with Qt.

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

 import QtQuick 2.0 Rectangle { signal clicked() MouseArea { anchors.fill: parent onClicked: { parent.clicked() // emit the parent 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) ... 
+13
source share

I would recommend sub classing QQuickView and set the property in its root context, for example MainWindow. Now you need to add functions in this class with decorations such as @pyqtSlot ('QString'), and then you can set the event handler using onClicked: MainWindow.FunctionName (Arguments_According_To_Decoration)

Then your main.py will look like this

 #!/bin/env python3 # -*- coding: utf-8 -*- from PyQt5.QtCore import pyqtSlot from PyQt5.QtCore import QUrl from PyQt5.QtQuick import QQuickView from PyQt5.QtWidgets import QApplication import sys class MainWindow(QQuickView): def __init__(self): super().__init__() self.setSource(QUrl('sample.qml')) self.rootContext().setContextProperty("MainWindow", self) self.show() @pyqtSlot('QString') def Print(self, value): print(value) if __name__ == '__main__': app = QApplication(sys.argv) w = MainWindow() sys.exit(app.exec_()) 

And sample.qml like that

 import QtQuick 2.0 import QtQuick.Controls 2.2 Rectangle { width: 200; height: 200 Button { text: "print Hello World" onClicked: MainWindow.Print('hello world') } } 

You can find more detailed information in the documents.

http://pyqt.sourceforge.net/Docs/PyQt5/signals_slots.html

+1
source share

All Articles