首先,困难的部分:
我已经看到了实现这一点的各种想法,但无法找到一个很好的例子来说明如何在我的 wxFrame 对象中创建自定义事件并从另一个线程调用它
wxPyWiki 上有一个关于此权利的示例。您可能还想查看在单独的线程中使用 wxPython的链接。
但是,我认为来自 The Mouse Vs的博客文章wxPython 和线程。Python 最好地解释了困难的部分。它还向您展示了执行此操作的更简单方法(使用CallAfter
而Publisher
不是发布自定义事件),但让我们坚持您询问的方式。
它唯一缺少的部分是:
......还有逻辑线程阻塞并等待输入返回,然后如何将该输入返回给gameThread。
但是没有什么关于 wx-speceific 的。很难将信息发送到 wx(或任何事件循环)的唯一原因是事件循环不能阻塞。您的逻辑线程可以阻塞,实际上应该. 所以,任何正常的线程同步机制都可以。
因此,您有一个线程想要永远阻塞直到一个值准备好,而另一个线程想要能够发送该值而不阻塞。Condition
您可以使用 a或 a轻松完成此操作Queue
。后者在这里可能有点矫枉过正,但它更灵活,所以让我们这样做,只是为了好玩。
我将从鼠标博客中获取示例,并使其每次后台线程发布一个EVT_RESULT
事件时,它都会阻塞,直到该事件被处理,然后返回一个它可以......记录或其他东西的字符串,我猜,它不是非常有用,但我想证明它传递了一些东西。
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)
在此示例中,GUI 线程self.q.put(text)
在updateDisplay
. 没有什么神奇的理由它必须在那里然后 - 只要它最终发生(并且恰好是 1 次),逻辑线程就会阻塞直到它发生。例如,该updateDisplay
方法可以创建一个新按钮,并self.q.put
在用户单击它时发送(并删除该按钮)。