← Back to top
Calling a function in the main thread in PyQt
As UI related function in Qt are limited to the main thread, now and again it's
useful to 'switch' from the current active thread to the main thread. One option
to achieve this is to use the
qtutils package. However, pulling
in a third party dependency for something that seems trivial is not very
satisfactory.
The easiest way to execute a function on the main thread is by initializing a
QObject while in the main thread (at the start of the application). A signal
part of this object is automatically bound to the main thread. This means that
slots connected to the signal are executed in the main thread. The
Qt signal-slot
connection type determines the blocking behaviour when emitting the signal.
# Save this file as InMain.py and import it
# while in the main thread (at the start of the application)
import queue as q
from PyQt5.QtCore import *
class InMain(QObject):
sig = pyqtSignal()
def __init__(self):
super().__init__()
self.queue = q.Queue()
# Notice we use a Qt.QueuedConnection here, change to your liking.
self.sig.connect(self.execute_funs, Qt.QueuedConnection)
def execute_funs(self):
while not self.queue.empty():
(fn, args, kwargs) = self.queue.get()
fn(*args, **kwargs)
def call(self, fn, *args, **kwargs):
"""Schedule a function to be called on the main thread."""
self.queue.put( (fn, args, kwargs) )
self.sig.emit()
inMain = InMain()
It's important to import the Python file containing this code while in the main
thread, otherwise (the QObject) inMain won't be part of the main thread. To call
a function in the main thread you can use:
from InMain import inMain
# ... somewhere in the code
inMain.call(fun_to_call, some_arg, keyword_arg=10)