How to make QtGui window process events whenever it is brought forward on the screen?
You should look into QThread.
Threads allow you to run long, complicated tasks in a worker thread while a background thread keeps the GUI responsive, such as updating a QProgressBar, ensuring it responds to motion events.
The basic idea is this:
# load modules
import time
from PySide import QtCore, QtGui
# APPLICATION STUFF
# -----------------
APP = QtGui.QApplication([])
# THREADS
# -------
class WorkerThread(QtCore.QThread):
'''Does the work'''
def __init__(self):
super(WorkerThread, self).__init__()
self.running = True
def run(self):
'''This starts the thread on the start() call'''
# this goes over 1000 numbers, at 10 a second, will take
# 100 seconds to complete, over a minute
for i in range(1000):
print(i)
time.sleep(0.1)
self.running = False
class BackgroundThread(QtCore.QThread):
'''Keeps the main loop responsive'''
def __init__(self, worker):
super(BackgroundThread, self).__init__()
self.worker = worker
def run(self):
'''This starts the thread on the start() call'''
while self.worker.running:
APP.processEvents()
print("Updating the main loop")
time.sleep(0.1)
# MAIN
# ----
def main():
# make threads
worker = WorkerThread()
background = BackgroundThread(worker)
# start the threads
worker.start()
background.start()
# wait until done
worker.wait()
if __name__ == '__main__':
main()
The output you get is something like this, showing how it takes turns at doing the long calculation and updating the main loop:
0
Updating the main loop
1
Updating the main loop
2
Updating the main loop
3
Updating the main loop
4
Updating the main loop
5
Updating the main loop
6
Updating the main loop
Updating the main loop7
8
Updating the main loop
9
This along with a QFocusEvent override should allow you to do whatever you wish. But it's better to separate updating the GUI and running your desired long thread.
As for overriding the QFocusEvent you can do something as follows:
def focusInEvent(self, event):
event.accept()
# insert your code here
And if you choose to implement threads to avoid GUI blocking, you should read about the basics of threading (as threads have a lot of nuances unless you know about their potential pitfalls).
Related videos on Youtube
pretzlstyle
Updated on June 04, 2022Comments
-
pretzlstyle almost 2 years
I'm using
PyQt
for Python, and am building a gui. I had a problem a few weeks ago where I had a function outside of the gui module modifying widgets within the gui (advanced progress bar, updating strings, etc.), and those modifications were not reflected in the gui until the function that had made the changes finished running.The solution to this was to simply call
app.processEvents()
after doing whatever modifications I wanted, which would immediately update the graphics of the window.But now I am wondering, is there a way to do this everytime the window is brought forward?
Let's say I have called a function that will be modifying the progress bar, but this function takes quite a while to run. Inbetween calling the function, and the progress bar modification, the
app
processes no events. So, it during this time, I pull up a Chrome window (or anything else), and then close it, my gui window is blank, just gray, untilapp.processEvents()
is called again.Is ther functionality in
PyQt
that allows me to detect whenever the window is brought to the front of all current windows?-
Mel over 8 yearsPossible duplicate of An event for focus changed?
-
Alex Huszagh over 8 yearsNot really @tmoreau, it's an issue of GUI-blocking.
focusChanged
is indeed a good signal when needed, orfocusInEvent
for their applications, but if the main thread is blocked, they will not be called until well after the long task finishes. -
Oliver over 8 yearsAlthough qthread is typically a better approach to long running functions, calling app.processEvents() might be sufficient if called from the right place and could lead to a much simpler fix to your issue. If you post the code in the vicinity of where you call app.processEvents() you might get an alternative approach.
-
-
pretzlstyle over 8 yearsThank you, this is certainly the best way to go. My program is fairly complex, and long, so making these changed would be a pretty massive overhaul. But it is necessary, the program feels shaky as it is and I always felt that it needed something like this. Thanks for the links and info.
-
Alex Huszagh over 8 yearsOf course, one thing I will mention is that make sure you know how resources are accessed if it could potentially be shared between two threads. Not all operations are atomic, which means if a resource is potentially shared between two threads, you could have unexpected results. (Most Python objects, however, are safe). If you need access to a resource between two threads, look into a QMutex: doc.qt.io/qt-4.8/qmutex.html