I want to run a long task in background and send signals to main thread to update the gui. The Applicatione becomes unresponisive at 1500th to 2000th iteration.
- First i call the
start_the_thread
function from qml to emit thestart
-signal. This starts the long task i want to run. - On every iteration i emit the
send_value
signal. This signal is connected to thesend_back_to_qml
function in main thread. - The
send_back_to_qml
function emits a SignalsendWordBack
. - The
sendWordBack
-signal is catched in QML with the help of aConnection {...}
. - In QML
onSendWordBack: {textArea.text += word}
append value to textarea field on every iteration.
Did i do something wrong with the implementation?
Are there ways to optimize this kind of operation?
main.py
import sys
import os
from PySide2.QtCore import QObject, QThread, Slot, Signal
from PySide2.QtGui import QGuiApplication
from PySide2.QtQml import QQmlApplicationEngine
import time
class BackgroundThread(QObject):
send_value = Signal(str)
start = Signal()
def __init__(self):
QObject.__init__(self)
# connect the start signal to heavy task function
self.start.connect(self.do_background_work)
def do_background_work(self):
for i in range(10000):
print(i)
self.send_value.emit(str(i))
time.sleep(0.1)
class BackendController(QObject):
sendWordBack = Signal(str, arguments=["word"])
def __init__(self):
QObject.__init__(self)
thread = QThread(self)
self.worker = BackgroundThread()
self.worker.moveToThread(thread)
self.worker.send_value.connect(self.send_back_to_qml)
thread.start()
@Slot()
def start_the_thread(self):
# emit the start signal from BackgroundThread() to start the background task
self.worker.start.emit()
@Slot(str)
def send_back_to_qml(self, value):
# emit the signal sendWordBack to send the value back to qml gui
self.sendWordBack.emit(value + '\n')
if __name__ == "__main__":
backend = BackendController()
app = QGuiApplication(sys.argv)
engine = QQmlApplicationEngine()
context = engine.rootContext()
context.setContextProperty('backend_call', backend)
engine.load(os.path.join(os.path.dirname(__file__), "main.qml"))
if not engine.rootObjects():
sys.exit(-1)
sys.exit(app.exec_())
main.qml
import QtQuick 2.13
import QtQuick.Window 2.13
import QtQuick.Controls 2.15
Window {
id: window
width: 640
height: 480
minimumWidth: 640
minimumHeight: 480
visible: true
color: "#dad8d8"
title: qsTr("Hello World")
Rectangle {
id: rectangle
width: parent.width
height: parent.height / 8
color: "#807272"
Text {
id: element
text: qsTr("PySide Example")
anchors.fill: parent
font.pixelSize: 20
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
Rectangle {
id: rectangle1
width: parent.width
color: "#ffffff"
anchors.top: rectangle.bottom
anchors.bottom: bootom_row.top
ScrollView {
id: scrollView
anchors.fill: parent
TextArea {
id: textArea
width: parent.width
text: ""
anchors.left: parent.left
anchors.top: parent.top
anchors.bottom: parent.bottom
font.pixelSize: 20
font.bold: true
placeholderText: qsTr("Text Area")
}
}
}
Row {
id: bootom_row
width: parent.width
height: parent.height / 8
anchors.bottom: parent.bottom
layoutDirection: Qt.LeftToRight
Button {
id: button
height: parent.height
text: qsTr("Button")
background: Rectangle {color: "#f3d27f"}
onClicked: {
backend_call.start_the_thread()
}
}
}
Connections {
target: backend_call
onSendWordBack: {
textArea.text += word
}
}
}
# self.worker.send_value.connect(self.send_back_to_qml)
– mthecreator