有很多非常相似的问题,但我找不到一个专门适用于我正在尝试做的事情的问题。
我有一个模拟(用 SimPy 编写),我正在为其编写一个 GUI,模拟的主要输出是文本 - 从"打印"语句到控制台。现在,我认为最简单的方法是创建一个单独的模块 GUI.py,并将我的模拟程序导入其中:
import osi_model
我希望所有打印语句都由 GUI 捕获并出现在 Textctrl 中,这里有无数的例子,如下所示:
class MyFrame(wx.Frame):
def __init__(self, *args, **kwds):
<general frame initialisation stuff..>
redir=RedirectText(self.txtCtrl_1)
sys.stdout=redir
class RedirectText:
def __init__(self,aWxTextCtrl):
self.out=aWxTextCtrl
def write(self,string):
self.out.WriteText(string)
我也从"开始"按钮开始模拟:
def go_btn_click(self, event):
print 'GO'
self.RT = threading.Thread(target=osi_model.RunThis())
self.RT.start()
这一切都工作正常,模拟模块的输出由 TextCtrl 捕获,除了 GUI 锁定并变得无响应 - 我仍然需要它可访问(至少有一个"停止"按钮)。我不确定这是否是我在这里完成的新线程的拙劣尝试,但我认为在此过程中的某个阶段将需要一个新线程。
人们建议使用wx。CallAfter,但考虑到导入的模块不知道 wx,我不确定该怎么做,而且我也无法实际浏览整个模拟架构并将所有打印语句更改为 wx。CallAfter,任何从导入的模拟程序内部捕获外壳的尝试都会导致程序崩溃。
有人对我如何最好地实现这一目标有任何想法吗?因此,我真正需要的只是在 GUI 保持响应的同时,由 TextCtrl 捕获所有控制台文本,并且所有文本仅来自导入的模块。
(另外,关于停止按钮的次要问题 - 只是杀死模拟线程是不好的形式吗?
谢谢
邓肯
我建议查看这篇关于长时间运行的任务的 WX wiki 文章。
它专门解决了您使用"开始"按钮处理的情况,使其成为长时间运行的过程。使用不同的技术(如线程和空闲处理程序)给出了几个不同的示例。
我认为您必须将 stdout 重定向到日志文件(或简单的 SQLite 数据库?),然后使用您的线程检查日志文件中的更新,然后它会使用 wx 传递给 GUI。呼叫后或类似。你也许可以使用像Python:http://wiki.wxpython.org/AsynchronousSockets 内置的套接字服务器这样的东西。我认为wxPython食谱也提到了一些关于使用RPC服务器的事情(可能是这个:http://docs.python.org/library/simplexmlrpcserver.html),但我不记得细节了。
您还应该尝试在官方wxPython邮件列表中询问。他们在那边非常友好。