从 wxpython 中导入的模块捕获标准输出并将其发送到文本控制,而不会阻塞 GUI



有很多非常相似的问题,但我找不到一个专门适用于我正在尝试做的事情的问题。

我有一个模拟(用 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邮件列表中询问。他们在那边非常友好。

相关内容

  • 没有找到相关文章

最新更新