First, the hard part:
I saw all kinds of ideas for implementing this, but could not find a good example of how to create a custom event in my wxFrame object and call it from another thread
Here is an example of this right in wxPyWiki . You can also see a link to Working with wxPython in a separate thread .
However, I think the wxPython blog post and themes are from The Mouse Vs. Python explains the hard part best. And it also shows you an easier way to do this (using CallAfter and Publisher instead of posting custom events), but let it stick to what you requested.
The only thing he lacks:
... and also have a logical thread block and wait until the input returns, and then how to get this input back to gameThread.
But nothing is said there. The only reason sending information to wx (or any event loop) is complicated because the event loop cannot be blocked. Your logical thread can block, but really should. So any normal thread synchronization mechanism is just fine.
So, you have one thread that wants to block forever until the value is ready, and another thread that wants to send this value without blocking. You can do this quite easily with Condition or Queue . The latter is probably crowded here, but it is more flexible, so let's do it just for fun.
I will take an example from the Mouse blog and make sure that every time the background thread dispatches the EVT_RESULT event, it blocks until this event is processed, returning a line that can ... write or something else, I I think this is not very useful, but I wanted to show that he was missing something.
from queue import Queue # ... class TestThread(Thread): # ... def run(self): for i in range(6): # ... wx.PostEvent(self.wxObject, ResultEvent(amtOfTime) result_from_gui = self.wxObject.q.get(True, None) # ... class MyForm(wx.Frame): # ... def __init__(self): # ... self.q = Queue() # ... def updateDisplay(self, msg): # ... t = msg.data if isinstance(t, int): text = "Time since thread started: %s seconds" % t else: text = "%s" % t self.btn.Enable() self.displayLbl.SetLabel(text) self.q.put(text)
In this example, the GUI thread executes self.q.put(text) at the end of updateDisplay . There is no magic reason why it should be there, and then - while this happens (and exactly 1 time), the logical flow will be blocked until this happens. For example, the updateDisplay method can create a new button and send self.q.put (and delete the button) when the user clicks on it.