Johan
Johan

Reputation: 899

Python PyQt separate backend from GUI

I want my Python backend to not have to wait for my PyQt GUI to draw (lots of) stuff. Is there a better/correct way of doing this in PyQt than like in the code example below? Is it necessary to use the threading import or does PyQt have its own better way of doing it?

import time
from threading import Thread

class Backend(Thread):
    def __init__(self):
        super().__init__()

    def run(self):
        for i in range(20):
            print("Backend heavy work")
            time.sleep(4)


class GUI(Thread):
    def __init__(self):
        super().__init__()

    def run(self):
        for i in range(20):
            print("GUI drawing stuff")
            time.sleep(0.5)

if __name__ == '__main__':
    thread_backend = Backend()
    thread_gui = GUI()

    thread_backend.start()
    thread_gui.start()

I tried doing it with Qtimer but didn’t get it to work. Thank you!

Upvotes: 0

Views: 1853

Answers (1)

buck54321
buck54321

Reputation: 847

You cannot update the UI from outside the Qt loop. What you can do is use qt signals to connect to methods to do the job for you. As an example

class GUI(QtCore.QObject): # must be a class that inherits QObject to use signals, I believe
    drawSignal = QtCore.pyqtSignal(int)
    def __init__(self):
        super().__init__()
        self.drawSignal.connect(self._drawStuff) # The underscore thing is a little hacky, but sort of pythonic I think, and makes the API clean.
        self.drawStuff = self.drawSignal.emit
    def _drawStuff(self, i):
        # do whatever you want to the gui here
        pass


class GUILoop(Thread):
    def __init__(self, gui):
        super().__init__()
        self.gui = gui
    def run(self):
        for i in range(20):
            self.gui.drawStuff(i)
            time.sleep(0.5)

if __name__ == '__main__':
    gui = GUI()
    thread_backend = Backend()
    thread_gui = GUILoop(gui)

    thread_backend.start()
    thread_gui.start()

It may seem a little weird, but it fits the strengths of both Qt and Python well. It probably also makes sense to just add the signals to your QMainWindow class, which already is a QObject.

Upvotes: 1

Related Questions