Using QThread in PyQt to Implement Background Threads in Python

Posted by


In PyQt, QThread is commonly used to run tasks in the background and keep the main GUI thread responsive. This allows you to perform time-consuming operations such as network requests, file I/O, and heavy calculations without freezing the user interface.

In this tutorial, we will create a simple PyQt application that demonstrates how to use QThread to run tasks in the background. We will create a main window with a button that triggers a time-consuming operation, and a progress bar that shows the progress of the operation.

Step 1: Install PyQt
First, you need to install PyQt on your system. You can install it using pip by running the following command in your terminal:

pip install PyQt5

Step 2: Create the main application
Next, create a new Python file and import the necessary modules:

from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QVBoxLayout, QProgressBar, QWidget
from PyQt5.QtCore import QThread, pyqtSignal
import sys
import time

Now, create a new class that will represent the main window of the application. In this class, we will create a button that triggers a time-consuming operation and a progress bar to show the progress of the operation:

class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()

        self.setWindowTitle("Background Thread with QThread")
        self.setGeometry(100, 100, 400, 200)

        self.layout = QVBoxLayout()

        self.button = QPushButton("Start Task")
        self.button.clicked.connect(self.start_task)
        self.layout.addWidget(self.button)

        self.progress_bar = QProgressBar()
        self.layout.addWidget(self.progress_bar)

        self.central_widget = QWidget()
        self.central_widget.setLayout(self.layout)
        self.setCentralWidget(self.central_widget)

    def start_task(self):
        self.worker = Worker()
        self.worker.start()

Step 3: Create the worker thread
Now, we need to create a worker class that will run the time-consuming operation in the background. We will subclass QThread and override the run method to define the task that needs to be performed:

class Worker(QThread):
    update_progress = pyqtSignal(int)

    def run(self):
        for i in range(101):
            time.sleep(0.1)  # Simulate a time-consuming operation
            self.update_progress.emit(i)

In the Worker class, we define a signal called update_progress that will be emitted to update the progress bar. Inside the run method, we loop through the range of 0 to 100, pausing for a short time between each iteration to simulate a time-consuming operation.

Step 4: Connect the worker thread to the progress bar
In the MainWindow class, we need to connect the update_progress signal emitted by the worker thread to a slot that updates the progress bar:

self.worker.update_progress.connect(self.update_progress_bar)

Next, we define the update_progress_bar method that updates the value of the progress bar:

def update_progress_bar(self, value):
    self.progress_bar.setValue(value)

Step 5: Run the application
Finally, we create an instance of the QApplication class and the MainWindow class, and start the application loop:

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

Now, when you run the application, you will see a main window with a button that triggers a time-consuming operation and a progress bar that updates as the operation progresses.

In this tutorial, we learned how to create a PyQt application that uses QThread to run tasks in the background. QThread is a powerful tool for keeping the main GUI thread responsive and running time-consuming operations efficiently. You can use this knowledge to create applications that perform complex calculations, network requests, and other tasks without impacting the user experience.