0

I am using a QThread and, when my worker class is dont with the big work, i want to call a function that does changes to my UI (in this case with .finished.connect(), but i dont fully understand how the .connect() step works and how i can pass variables to the function called.

As an example: A button that, when pressed, opens a Thread in which it counts up, and changes the button text to the number its on. When the counter is finished, it prints something. Very simple and it works just fine.

main.py:

from PyQt5 import QtWidgets
import sys
import worker
from PyQt5.QtCore import QThread
from start import test


class App(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(App, self).__init__(parent)
        self.init_ui()
        self.initiate_buttons()
        self.obj = worker.Worker()
        self.thread = QThread()
        self.obj.intReady.connect(self.onIntReady)
        self.obj.moveToThread(self.thread)
        self.obj.finished.connect(self.thread.quit)
        self.obj.finished.connect(test)
        self.thread.started.connect(self.obj.procCounter)


    def init_ui(self):
        self.pushButton = QtWidgets.QPushButton(self)

    def onIntReady(self, i):
        self.pushButton.setText("{}".format(i))

    def initiate_buttons(self):
        print("clicked")
        self.pushButton.clicked.connect(lambda: self.thread.start())

def run():
    application = QtWidgets.QApplication(sys.argv)
    main_app = App()
    main_app.show()
    application.exec()

if __name__ == '__main__':
    run()

worker.py:

from PyQt5.QtCore import QObject, pyqtSignal, pyqtSlot
import time


class Worker(QObject):
    finished = pyqtSignal()
    intReady = pyqtSignal(int)

    @pyqtSlot()
    def procCounter(self):
        for i in range(1, 5):
            time.sleep(1)
            self.intReady.emit(i)

        self.finished.emit()

start.py:

def test(x="bar"):
    print("test"+x)

So the thing i am talking about is start.py - i can put the function in its own module just fine and it worked. But what if i want to pass a parameter to it? I tried the obvious attempt, changing self.obj.finished.connect(test) to self.obj.finished.connect(test(x="foo")) - but that doesnt work. But i dont understand why it does not work, and how else i am supposed to do this. In the end, i want the module to do changes to my UI, just like onIntReady. I found this and this but did not understand how i can apply it.

Flying Thunder
  • 890
  • 2
  • 11
  • 37
  • 1
    If you want it to work "just like onIntReady" then why don't you simply do exactly that? Or use a `lambda` - as you have also already done elsewhere in your code. – ekhumoro Dec 15 '21 at 14:52
  • Ah, you are right, i didnt think the .connect() would work the same as in other places, i just copied this example from SO and it didnt use lambda - thanks!! – Flying Thunder Dec 16 '21 at 08:59
  • But the thing i also ment is, for example, when i want to move `self.onIntReady` to another module - sure i can pass variables to it by using `lambda: self.onIntReady(x)` - but when i do that, i no longer pass `intReady` to it, and i dont know how i would do that - for example `.connect(lambda: self.onIntReady(self.obj.intReady, x)` doesnt work, so how would i pass the current value of the signal to the variable? – Flying Thunder Dec 16 '21 at 14:10
  • 1
    `connect(lambda arg: slot(arg))`. I suggest you read some basic pyqt tutorials rather than copy/pasting random code that you don't understand. – ekhumoro Dec 16 '21 at 16:12

0 Answers0