Prevent Freezing in Python PYQT GUIs with QThread
Last Updated :
28 May, 2024
When performing long-running tasks, GUIs can become unresponsive or "freeze," frustrating users and making the application appear unprofessional. This is a common problem in applications built with PyQt, a set of Python bindings for the Qt application framework. To address this issue, PyQt provides QThread, a class that allows developers to run code in separate threads, keeping the GUI responsive. This article will introduce PyQt's QThread and demonstrate two different methods to use it to prevent GUI freezing.
What is PyQt's QThread?
QThread is a class in PyQt that allows developers to run code in parallel with the main thread, which handles the GUI. By moving time-consuming operations to a QThread, the main thread remains free to handle user interactions and updates, preventing the application from freezing.
Understanding GUI Freezing
GUI freezing typically occurs when time-consuming operations, such as data processing or network requests, are performed within the main thread of the application. Since the main thread is responsible for handling user input and updating the interface, performing intensive tasks in this thread can cause the GUI to become unresponsive. This results in a poor user experience, as users may perceive the application as slow or unresponsive.
Illustrate the Issue with a Simple Example
Consider a PyQt application that calculates the factorial of a large number when a button is clicked. Here's how the code might look:
In this example, clicking the "Calculate Factorial" button triggers a time-consuming calculation of the factorial of a large number. Since this calculation is performed within the main thread, the GUI becomes unresponsive until the calculation is complete, resulting in a frozen interface.
Python
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QLabel
def calculate_factorial():
result = 1
for i in range(1, 100000):
result *= i
return result
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("GUI Freezing Example")
self.setGeometry(100, 100, 300, 200)
self.label = QLabel(self)
self.label.setGeometry(50, 50, 200, 30)
self.button = QPushButton("Calculate Factorial", self)
self.button.setGeometry(50, 100, 200, 30)
self.button.clicked.connect(self.on_button_click)
def on_button_click(self):
factorial = calculate_factorial()
self.label.setText(f"Factorial: {factorial}")
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
Output:
Due to the large factorial, it's not calculating and freezing the GUI with an error message.

ValueError: Exceeds the limit (4300 digits) for integer string conversion; use sys.set_int_max_str_digits() to increase the limit
Preventing GUI Freezes in Python with PYQT QThread
To prevent GUI freezing, we can use PyQt's QThread to perform time-consuming tasks in separate threads. By moving intensive operations to separate threads, we ensure that the main thread remains available to handle user input and update the interface.
Let's modify the previous example to use QThread for calculating the factorial in a separate thread:
In this modified example, we create a subclass of QThread called FactorialThread to perform the factorial calculation in a separate thread. The run method of FactorialThread performs the calculation, and once it's complete, it emits a signal result_ready containing the calculated factorial. We connect this signal to a slot on_factorial_calculated in the MainWindow class, which updates the GUI with the result.
By using QThread to perform the factorial calculation in a separate thread, the main GUI thread remains responsive, and users can continue interacting with the application while the calculation is ongoing.
Python
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QLabel
from PyQt5.QtCore import QThread, pyqtSignal
class FactorialThread(QThread):
result_ready = pyqtSignal(int)
def __init__(self):
super().__init__()
def run(self):
result = 1
for i in range(1, 100000):
result *= i
self.result_ready.emit(result)
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("QThread Example")
self.setGeometry(100, 100, 300, 200)
self.label = QLabel(self)
self.label.setGeometry(50, 50, 200, 30)
self.button = QPushButton("Calculate Factorial", self)
self.button.setGeometry(50, 100, 200, 30)
self.button.clicked.connect(self.on_button_click)
self.thread = FactorialThread()
self.thread.result_ready.connect(self.on_factorial_calculated)
def on_button_click(self):
self.button.setEnabled(False)
self.thread.start()
def on_factorial_calculated(self, result):
self.label.setText(f"Factorial: {result}")
self.button.setEnabled(True)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
Output

Conclusion
GUI freezing can significantly degrade the user experience of an application. By leveraging PyQt's QThread, developers can prevent GUI freezing by offloading time-consuming tasks to separate threads. This ensures that the main thread remains available to handle user input and update the interface, resulting in a smoother and more responsive user experience.
Similar Reads
Python PyQt5 - Hiding the Progress Bar ? In this article we will see how to hide the progress bar in PyQt5 application. There two ways in which we can hide the progress - Using hide method.Setting visibility status of progress bar to False. Method #1 : With the help of hide method, we can hide the progress bar. Below is the implementation.
2 min read
Creating Your Own Python IDE in Python In this article, we are able to embark on an adventure to create your personal Python Integrated Development Environment (IDE) the usage of Python itself, with the assistance of the PyQt library. What is Python IDE?Python IDEs provide a characteristic-rich environment for coding, debugging, and goin
3 min read
PyQt5 QCalendarWidget - Ensuring Paint event In this article we will see how we can ensure the paint event of the QCalendarWidget. With the help of painter events we can paint the calendar however user wants it to be, but some times there is a need to repaint the spin box to ensure the painter event action. In order to do this we will use rep
1 min read
Python GUI - PyQt VS TKinter A GUI toolkit contains widgets that are used to create a graphical interface. Python includes a wide range of Interface implementations available, from TkInter (it comes with Python, ) to a variety of various cross-platform solutions, such as PyQt5, which is known for its more sophisticated widgets
5 min read
PyQt5 Input Dialog | Python PyQt5 provides a class named QInputDialog which is used to take input from the user. In most of the application, there comes a situation where some data is required to be entered by the user and hence input dialog is needed. Input can be of type String or Text, Integer, Double and item.Used methods:
2 min read