Running the wx's event loop manually

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

Running the wx's event loop manually

oliver2213
Hi.
I'm not particularly new to wx python, but I'm having trouble accomplishing something I need for a game I'm writing.
As I understand it, the event loop is what "drives" the gui (reacting to events sent by the toolkit as well as user code).
The normal method of starting this is with an app instance's MainLoop method, which is about as blocking of a blocking call as you can get.
My game uses pyglet, but I really want wx for certain UI elements, and I'd rather not put the event loop into another thread if I can help it. So I'm trying to "drive" the loop on an interval from the main thread (if evtloop.Pending(): evtloop.Dispatch(), as a simple example).
The app class I'm using is attached, but for some reason I can't fathom, it doesn't work. Also, when I run app.GetMainLoop(), I get none, so my code isn't registering it's main loop properly, I guess. When I run the Show() method of any dialog, nothing happens, so I feel like it's this "wx doesn't think of my loop as the app's event loop" problem that's the real issue here.
If anyone could help, I would appreciate it, been looking into this for a few hours and I'm coming up blank; also posted a question on stack overflow (though it doesn't have the code I've attached here).

--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.

wx_overrides.py (1K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Running the wx's event loop manually

Tim Roberts
[hidden email] wrote:
>
> I'm not particularly new to wx python, but I'm having trouble
> accomplishing something I need for a game I'm writing.
> As I understand it, the event loop is what "drives" the gui (reacting
> to events sent by the toolkit as well as user code).

Yes.  This same concept is used in all of the major operating systems today.


> The normal method of starting this is with an app instance's MainLoop
> method, which is about as blocking of a blocking call as you can get.
> My game uses pyglet, but I really want wx for certain UI elements, and
> I'd rather not put the event loop into another thread if I can help it.

Well, in fact, you CAN'T do that arbitrarily.  Events are sent to a
thread, not to a process.  Your event loop must run in the same thread
that created the windows.  Usually, that's the main thread, although
it's possible to create windows and manage them from a secondary thread.

Did you do any web searching?  There are a couple of posts on combining
Pyglet and wxPython.  It looks like the normal plan is to let wxPython
do its main loop the way it wants, then have a separate Pyglet thread
that fires a custom wx event at the redraw interval.  That seems like a
much cleaner design.


> So I'm trying to "drive" the loop on an interval from the main thread
> (if evtloop.Pending(): evtloop.Dispatch(), as a simple example).
> The app class I'm using is attached, but for some reason I can't
> fathom, it doesn't work.

How fast is your loop interval?  You're only allowing one window event
per loop, and window creation spews a LOT of messages.


> Also, when I run app.GetMainLoop(), I get none, so my code isn't
> registering it's main loop properly, I guess.

Right, because you are overriding the wx.App.MainLoop call that normally
creates the main loop.  That's normally all done in C++, but the C++
code doesn't know anything about your self.evtloop variable.

--
Tim Roberts, [hidden email]
Providenza & Boekelheide, Inc.

--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Running the wx's event loop manually

oliver2213
In reply to this post by oliver2213
Is there a way to register my event loop so it gets recognized? Not sure what GetMainLoop is checking, or i'd manually set it.
The interval is
every 50 ms, and roughly 2 seconds between ProcessIdle() calls.
Also, I tried using that class with a wx.TextEntryDialog instead of wx.MessageDialog, and it... Kind of worked. It pops up the dialog, but pressing tab or shift tab only moves me once, and will never move focus around again. I've tried playing with how frequently idle events are processed, but it doesn't seem to make a difference. I can type just fine in the field though, and the buttons work, so I'm not sure what's up.

Thanks for the tip about only processing one event, I'll change that if to be a while loop.
On Thursday, August 24, 2017 at 7:05:00 PM UTC-4, [hidden email] wrote:
Hi.
I'm not particularly new to wx python, but I'm having trouble accomplishing something I need for a game I'm writing.
As I understand it, the event loop is what "drives" the gui (reacting to events sent by the toolkit as well as user code).
The normal method of starting this is with an app instance's MainLoop method, which is about as blocking of a blocking call as you can get.
My game uses pyglet, but I really want wx for certain UI elements, and I'd rather not put the event loop into another thread if I can help it. So I'm trying to "drive" the loop on an interval from the main thread (if evtloop.Pending(): evtloop.Dispatch(), as a simple example).
The app class I'm using is attached, but for some reason I can't fathom, it doesn't work. Also, when I run app.GetMainLoop(), I get none, so my code isn't registering it's main loop properly, I guess. When I run the Show() method of any dialog, nothing happens, so I feel like it's this "wx doesn't think of my loop as the app's event loop" problem that's the real issue here.
If anyone could help, I would appreciate it, been looking into this for a few hours and I'm coming up blank; also posted a question on stack overflow (though it doesn't have the code I've attached here).

--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Running the wx's event loop manually

Robin Dunn
In reply to this post by oliver2213
You need to create a class derived from wx.GUIEventLoop to implement your custom event loop. You can then use that in your replacement of the MainLoop method. See the example at https://github.com/wxWidgets/Phoenix/blob/master/samples/mainloop/mainloop.py

On Thu, Aug 24, 2017 at 6:04 PM, <[hidden email]> wrote:
Hi.
I'm not particularly new to wx python, but I'm having trouble accomplishing something I need for a game I'm writing.
As I understand it, the event loop is what "drives" the gui (reacting to events sent by the toolkit as well as user code).
The normal method of starting this is with an app instance's MainLoop method, which is about as blocking of a blocking call as you can get.
My game uses pyglet, but I really want wx for certain UI elements, and I'd rather not put the event loop into another thread if I can help it. So I'm trying to "drive" the loop on an interval from the main thread (if evtloop.Pending(): evtloop.Dispatch(), as a simple example).
The app class I'm using is attached, but for some reason I can't fathom, it doesn't work. Also, when I run app.GetMainLoop(), I get none, so my code isn't registering it's main loop properly, I guess. When I run the Show() method of any dialog, nothing happens, so I feel like it's this "wx doesn't think of my loop as the app's event loop" problem that's the real issue here.
If anyone could help, I would appreciate it, been looking into this for a few hours and I'm coming up blank; also posted a question on stack overflow (though it doesn't have the code I've attached here).

--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.



--
Robin Dunn
Software Craftsman
http://wxPython.org

--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Running the wx's event loop manually

Tim Roberts
In reply to this post by oliver2213
[hidden email] wrote:
>
> Is there a way to register my event loop so it gets recognized? Not
> sure what GetMainLoop is checking, or i'd manually set it.

It's a member variable in the C++ structure.  I don't believe it is
exposed to Python.


> The interval is every 50 ms, and roughly 2 seconds between
> ProcessIdle() calls.

Two seconds is an eternity.  The standard code calls ProcessIdle as soon
as the message queue goes empty, but only once.


> Also, I tried using that class with a wx.TextEntryDialog instead of
> wx.MessageDialog, and it... Kind of worked. It pops up the dialog, but
> pressing tab or shift tab only moves me once, and will never move
> focus around again. I've tried playing with how frequently idle events
> are processed, but it doesn't seem to make a difference. I can type
> just fine in the field though, and the buttons work, so I'm not sure
> what's up.

Well, let me be honest for a moment.  I think you are going about this
the wrong way, and your choices are causing you to butt heads with the
internal design of wxWidgets.  You are exploring deep into hackery,
which is going to be delicate and difficult to maintain, and it is
entirely unnecessary.  The proper solution is to let wxPython do its
normal main loop stuff, and find a way to satisfy Pyglet with that. 
That can be done easily, and in a fully supported manner.

50ms is easy.  You could use a wx.Timer on a 50ms interval, and have the
EVT_TIMER handler go do your Pyglet rendering.  That would produce
exactly the same results you have now with your custom inner loop, but
in a way that is supported and well-understood.

--
Tim Roberts, [hidden email]
Providenza & Boekelheide, Inc.

--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Running the wx's event loop manually

oliver2213
In reply to this post by Robin Dunn
I actually based my app subclass off that example (though it doesn't subclass GUIEventLoop).
I don't really need to change how the event loop works, I just need to change *when* it works. I could try redefining Run() in a GUIEventLoop subclass that returns immediately like the code I attached above does, but if I still override MainLoop() in my app subclass, any c code that runs that sets the current event loop still won't run.
I also meant to mention this in the original post, but I'm using Phoenix 4.0.0b1 with python 2.7 on windows 10.


On Friday, August 25, 2017 at 12:24:12 PM UTC-4, Robin Dunn wrote:
You need to create a class derived from wx.GUIEventLoop to implement your custom event loop. You can then use that in your replacement of the MainLoop method. See the example at <a href="https://github.com/wxWidgets/Phoenix/blob/master/samples/mainloop/mainloop.py" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2FwxWidgets%2FPhoenix%2Fblob%2Fmaster%2Fsamples%2Fmainloop%2Fmainloop.py\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNH3pEmr3kcKugMuUL6x2urSV-C_Jg&#39;;return true;" onclick="this.href=&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2FwxWidgets%2FPhoenix%2Fblob%2Fmaster%2Fsamples%2Fmainloop%2Fmainloop.py\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNH3pEmr3kcKugMuUL6x2urSV-C_Jg&#39;;return true;">https://github.com/wxWidgets/Phoenix/blob/master/samples/mainloop/mainloop.py

On Thu, Aug 24, 2017 at 6:04 PM, <<a href="javascript:" target="_blank" gdf-obfuscated-mailto="Z5tpAV-TAgAJ" rel="nofollow" onmousedown="this.href=&#39;javascript:&#39;;return true;" onclick="this.href=&#39;javascript:&#39;;return true;">olive...@...> wrote:
Hi.
I'm not particularly new to wx python, but I'm having trouble accomplishing something I need for a game I'm writing.
As I understand it, the event loop is what "drives" the gui (reacting to events sent by the toolkit as well as user code).
The normal method of starting this is with an app instance's MainLoop method, which is about as blocking of a blocking call as you can get.
My game uses pyglet, but I really want wx for certain UI elements, and I'd rather not put the event loop into another thread if I can help it. So I'm trying to "drive" the loop on an interval from the main thread (if evtloop.Pending(): evtloop.Dispatch(), as a simple example).
The app class I'm using is attached, but for some reason I can't fathom, it doesn't work. Also, when I run app.GetMainLoop(), I get none, so my code isn't registering it's main loop properly, I guess. When I run the Show() method of any dialog, nothing happens, so I feel like it's this "wx doesn't think of my loop as the app's event loop" problem that's the real issue here.
If anyone could help, I would appreciate it, been looking into this for a few hours and I'm coming up blank; also posted a question on stack overflow (though it doesn't have the code I've attached here).

--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to <a href="javascript:" target="_blank" gdf-obfuscated-mailto="Z5tpAV-TAgAJ" rel="nofollow" onmousedown="this.href=&#39;javascript:&#39;;return true;" onclick="this.href=&#39;javascript:&#39;;return true;">wxpython-user...@googlegroups.com.
For more options, visit <a href="https://groups.google.com/d/optout" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://groups.google.com/d/optout&#39;;return true;" onclick="this.href=&#39;https://groups.google.com/d/optout&#39;;return true;">https://groups.google.com/d/optout.



--
Robin Dunn
Software Craftsman
<a href="http://wxPython.org" target="_blank" rel="nofollow" onmousedown="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2FwxPython.org\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNHG9kM-NEpJfIvl_lWJvA23SuLjOA&#39;;return true;" onclick="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2FwxPython.org\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNHG9kM-NEpJfIvl_lWJvA23SuLjOA&#39;;return true;">http://wxPython.org

--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Running the wx's event loop manually

oliver2213
In reply to this post by Tim Roberts
I appreciate the honesty. The only reason I'm doing it this way is because most of the "work" is happening in the pyglet loop, and wx UI stuff won't be all that frequent, so I thought it would make more sense to move the wx loop forward from pyglet's.
If this gives me too much more trouble I'll rework things so pyglet's loop is driven by wx, but before I do that I'm going to try probably what I should have first: redefining AppTraits.CreateEventLoop() or whatever it's called.
As far as I understand it, that's where App.MainLoop() gets it's event loop instance, and if it works I won't need my app subclass, so whatever c code that handles registering the main loop properly can run.


On Friday, August 25, 2017 at 1:10:32 PM UTC-4, Tim Roberts wrote:
<a href="javascript:" target="_blank" gdf-obfuscated-mailto="-QNEIuaVAgAJ" rel="nofollow" onmousedown="this.href=&#39;javascript:&#39;;return true;" onclick="this.href=&#39;javascript:&#39;;return true;">olive...@... wrote:
>
> Is there a way to register my event loop so it gets recognized? Not
> sure what GetMainLoop is checking, or i'd manually set it.

It's a member variable in the C++ structure.  I don't believe it is
exposed to Python.


> The interval is every 50 ms, and roughly 2 seconds between
> ProcessIdle() calls.

Two seconds is an eternity.  The standard code calls ProcessIdle as soon
as the message queue goes empty, but only once.


> Also, I tried using that class with a wx.TextEntryDialog instead of
> wx.MessageDialog, and it... Kind of worked. It pops up the dialog, but
> pressing tab or shift tab only moves me once, and will never move
> focus around again. I've tried playing with how frequently idle events
> are processed, but it doesn't seem to make a difference. I can type
> just fine in the field though, and the buttons work, so I'm not sure
> what's up.

Well, let me be honest for a moment.  I think you are going about this
the wrong way, and your choices are causing you to butt heads with the
internal design of wxWidgets.  You are exploring deep into hackery,
which is going to be delicate and difficult to maintain, and it is
entirely unnecessary.  The proper solution is to let wxPython do its
normal main loop stuff, and find a way to satisfy Pyglet with that. 
That can be done easily, and in a fully supported manner.

50ms is easy.  You could use a wx.Timer on a 50ms interval, and have the
EVT_TIMER handler go do your Pyglet rendering.  That would produce
exactly the same results you have now with your custom inner loop, but
in a way that is supported and well-understood.

--
Tim Roberts, <a href="javascript:" target="_blank" gdf-obfuscated-mailto="-QNEIuaVAgAJ" rel="nofollow" onmousedown="this.href=&#39;javascript:&#39;;return true;" onclick="this.href=&#39;javascript:&#39;;return true;">ti...@...
Providenza & Boekelheide, Inc.

--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.