I have an application with a very dynamic UI (UI layout changes constantly with many new controls appearing and disappearing regularly).
I have a recurring, moderately long-duration (typically a few seconds) task that runs in the UI thread. (It must run in the UI thread as it is directly related to computations related to the UI changes I just mentioned).
I want to refresh my UI (layout/refresh, etc.) during the task so the application does not feel unresponsive for that long.
I have been using wx.Yield
during the “long task” but it does not work perfectly because I want to avoid calling the handler for command events or for events generated by wx.CallAfter
during the Yield
since those depend on the “long task” having been completed.
I have tried to use YieldFor
instead of Yield
: wx.EventLoopBase.GetActive().YieldFor(wx.EVT_CATEGORY_UI)
but my CallAfter
methods are still being called during the yield.
Is there a way of specifying argumens in YieldFor
to avoid CallAfter
events?
If it turns out that I cannot avoid CallAfter
events in YieldFor
(which I fear because browsing https://github.com/wxWidgets/wxWidgets/blob/71a64c25faeeafa558162a47fd125919c7a4f752/include/wx/event.h suggests that CallAfter
generates wxAsyncMethodCallEvent
that are somehow special) then,
Is there a way of generating custom events in wxPython for which GetEventCategory
does not return wx.EVT_CATEGORY_UI
?
(If so I could replace my calls to wx.CallAfter
with posting of these custom events that would be ignored during my YieldFor
.)
Thank you in advance!
[By the way suggestions to refactor the application to avoid the long task or to break it into smaller chunks would not be helpful: The application is already multithreaded and the “long task” in the UI thread really is distilled to the minimum necessary with all non-UI work already moved to other threads]
I’m not 100% sure what you’re trying to achieve here but is there a reason you don’t declare a `wx.lib.newevent.NewEvent()´ then when you receive that, you can perform whatever specific actions are required.
I’m far from Dev, actually playing user, but what about GetEventCategory
(self )
and filtering wxEVT_CATEGORY_THREAD
I personally don’t believe in messing around in the loop (especially from far away as python) and would stick to pursue other paths
Thank you.
I was able to solve my problem with virtually no coding by using wx.CallLater(0, my_callback)
which posts an event of category wx.EVT_CATEGORY_TIMER
, which gets skipped during yields triggered by wx.EventLoopBase.GetActive().YieldFor(wx.EVT_CATEGORY_UI)
instead of wx.CallAfter(my_callback)
which posts some internal event type that seems to always get processed during yields regardless of category filtering.
For the record, if I had not thought of this shortcut, next I was planning to investigate subclassing PyEvent
to overwrite GetEventCategory
to return wx.EVT_CATEGORY_THREAD
instead of wx.EVT_CATEGORY_UI
which PyEvent
returns. And then creating those events by mimicking the implementation of wx.lib.newevent.NewEvent()
, but returning an event of my class instead of PyEvent
, and then posting one of those based on the feedback above.
I always wondered what this wx.CallLater could be good for
it’s just a wrapper around wx.Timer and that generates a wx internal event: proper category etc (I assume when you talk of type you mean category)
there is no SetEventCategory and
wx.Event implementation returns wxEVT_CATEGORY_UI
by default
so I can’t see how one could possibly filter non generic event categories via YieldFor
I assume when you talk of type you mean category
Thank you. Indeed. I fixed it in the original post for clarity.
there is no SetEventCategory and
wx.Event implementation returns wxEVT_CATEGORY_UI
by default
so I can’t see how one could possibly filter non generic event categories via YieldFor
I was planning to subclass PyEvent
and implement GetEventCategory
in my subclass so that it would return wxEVT_CATEGORY_THREAD
. I have not tried it and I am not sure if the wxWidgets would have picked up my python method though.
I’m afraid subclassing PyEvent
will be a dead end and these other EventCategories
are wx internals, or at least not meant to be used from wxPython (there are threading classes in wx & this CATEGORY_THREAD
will be used by those, I think)
but Python has much more to offer than threads and if your Gui is chocked then you should move everything else into a different process (look at a browser how many workers they pull up right from the start ) and do in the Gui process only Gui stuff
here is a nice example of a process pool executor