Unsolved Push buttons and pixmaps not updating/refreshing properly in PyQt only on MacOS
-
Re: Layout not "updating" when removing all widgets inside it
Similar issue to the thread referenced above ^^. When doing certain GUI events (enabling/disabling buttons, clicking buttons, drawing pixamps, etc), they randomly are not being updated (i.e. the buttons are getting "stuck" in the pressed state). This happens for ALL push buttons on my GUI. So for example a user clicks a button, the program does things, but the button is still in the pressed state (the buttons are not set to toggle) but the user can clearly keep clicking the button and the program continues to function as normal.
This issue only exists for macOS, I have never seen this problem in a PyQt build on PC. I'm also doing multithreading, so that when a user clicks a button on the GUI, a new thread is created that does non-gui calculations, then upon finishing notifies the GUI to enable/disable certain buttons based on the operation. Therefore, the main GUI thread is always freed up to do the things it needs to do.
I've seen this on PyQt 5.12 using Python 3.5x and 3.7x.
Right now, I'm resorting to having a function that gets called when I emit a signal that goes in and manually calls .setEnabled(true) followed by .setEnabled(false). I then call .repaint() on each button. Manually setting setEnabled is the only way to get the .repaint() function to do anything.
Anybody else seeing similar issues? Can anyone verify they've seen this issue on PC too?
-
@Denni-0 Yes, they are sub-classed. I followed the implementation used here: https://www.learnpyqt.com/courses/concurrent-execution/multithreading-pyqt-applications-qthreadpool/.
The GUI is not getting hung up during computationally expensive processes so I'm assuming the 'multithreading' is working as intended. Also, this was happening before I even implemented multithreading for my app (having a more responsive GUI was the main reason for wanting to implement multithreading in the first place). So I don't believe it is related to threading.
What's confusing to me is why does the GUI never eventually update? If the event queue is being dominated by non-gui stuff, how do subsequent GUI events get handled as they move up in the queue? Certain interactions with the GUI (i.e. minimizing windows, starting other processed in the GUI) will cause some components to update/refresh but not all of them get updated. Other times, everything works just fine!
Also, calling .update() on the affected widget doesn't appear to do anything (the button still shows as being pressed even though I can still click it and have it do stuff). I've even tried adding a processEvents() call after updating the widgets to force the GUI to have control of the event loop and it still doesn't update things. This is super frustrating, any ideas?
-
Hi anybody welcome to devnet,
Would it be possible to take a look at your code ?
By the way, what version of Python and PyQt 5 are you using ?
How did you install them ? -
@SGaist The problem is that my GUI is fairly complex. I could put together a small working example with a widget and a couple of push buttons if I need to. Although I'd be willing to bet anybody running a PyQt GUI on macOS Sierra and above is going to see this problem.
This was tested on PyQt 5.12 using Python 3.5 and Python 3.7. Packages were installed using Anaconda/pip.
-
It would be most useful if you can build such an example. That would help debug your issue.
-
@Denni-0 Ok, that's good to know! I'm definitely interested in using QThread the proper way. I will hit you up soon to get your feedback.
In the meantime, I'm going to put together a minimal working example that doesn't use any threading to demonstrate the original issue for people using PyQT on macOS. I'll post it here soon...
-
I'm here to report that I have this exact same issue on Qt 5.12.3 under OSX using C++ directly.
I have this in two very different parts of my rather large GUI, both having to do with background threads.The clicked event of the pushbutton never arrives to my slot in some cases if there is ongoing background work.
I do not have this issue under Windows, and never had.I agree with wunjo that no matter how badly we might have implemented the background thread, the clicked event of the pushbutton should arrive on the event queue of the main thread eventually, but never actually does. (I'm using QThreadPool and add tasks to it using _pool.start(QRunnable *);)
I'll check if the clicked event somehow wrongly gets sent to the background thread and report back.
-
My minimal example to reproduce doesn't reproduce the problem.
In my original software, funnily enough, I receive the pressed() event from the pushbutton, but not the released() event in the error-cases. This also explains, why the button visualization stays in "down" state, it seems not even Qt is getting the up event somehow.
-
In my software the issue is not occuring on Qt 5.12.5 and also not on 5.13.1. So the easiest solution to the problem would probably be to just upgrade Qt.
-
@Denni-0 I know all of this, and I have never subclassed QThread in my software. As stated above I am using QThreadPool and QRunnable.
Nevertheless, I had the exact same problem as the original poster on OSX (and only there), and it went away with newer Qt versions.Either way, thanks for your effort and your answers!