From QML, I'd like to:
- Call a Python slot.
- Pass along a callback.
- Have that callback be run once the slot is complete.
I've tried this:
- Register a context-property (
Service) - Call
Service.request("data", function (response) { console.log(response) } - In Python, the function is received as a
QtQml.QJSValue - The function is called in a separate thread, after some expensive operation
However, the function only has an effect sometimes, and most of the time not at all or crashes the Python interpreter. If I remove the call to time.sleep(1), it is more likely to produce results.
Any ideas?
Here's a non-working implementation of the above
main.qml
import QtQuick 2.3
import "application.js" as App
Rectangle {
id: appWindow
width: 200
height: 200
Component.onCompleted: App.onLoad()
}
main.py
import sys
import time
import threading
from PyQt5 import QtCore, QtGui, QtQml, QtQuick
class Service(QtCore.QObject):
def __init__(self, parent=None):
super(Service, self).__init__(parent)
@QtCore.pyqtSlot(str, str, QtCore.QVariant, QtQml.QJSValue)
def request(self, verb, endpoint, data, cb):
"""Expensive call"""
print verb, endpoint, data
self.cb = cb
def thread():
time.sleep(1)
event = QtCore.QEvent(1000)
event.return_value = "expensive result"
QtGui.QGuiApplication.postEvent(self, event)
worker = threading.Thread(target=thread)
worker.daemon = False
worker.start()
self.worker = worker
def event(self, event):
if event.type() == 1000:
self.cb.call([event.return_value])
return super(Service, self).event(event)
app = QtGui.QGuiApplication(sys.argv)
view = QtQuick.QQuickView()
context = view.rootContext()
service = Service()
context.setContextProperty("Service", service)
view.setSource(QtCore.QUrl("main.qml"))
view.show()
app.exec_()
application.js
"use strict";
/*global print, Service*/
function onLoad() {
Service.request("POST", "/endpoint", {"data": "value"}, function (reply) {
print(reply);
print(reply);
print(reply);
});
print("request() was made");
}
The implementation is adapted from here
https://github.com/ben-github/PyQt5-QML-CallbackFunction
Best,
Marcus