2

There are alot of very similar questions to this but I can't find one that applies specifically to what I'm trying to do.

I have a simulation (written in SimPy) that I'm writing a GUI for, the main output of the simulation is text - to the console from 'print' statements. Now, I thought the simplest way would be to create a seperate module GUI.py, and import my simulation program into it:

import osi_model

I want all the print statements to be captured by the GUI and appear inside a Textctrl, which there's countless examples of on here, along these lines:

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)

I am also starting my simulation from a 'Go' button:

def go_btn_click(self, event):
    print 'GO'
    self.RT = threading.Thread(target=osi_model.RunThis())
    self.RT.start()

This all works fine, and the output from the simulation module is captured by the TextCtrl, except the GUI locks up and becomes unresponsive - I still need it to be accessible (at the very minimum to have a 'Stop' button). I'm not sure if this is a botched attempt at creating a new thread that I've done here, but I assume a new thread will be needed at some stage in this process.

People suggest using wx.CallAfter, but I'm not sure how to go about this considering the imported module doesn't know about wx, and also I can't realistically go through the entire simulation architecture and change all the print statements to wx.CallAfter, and any attempt to capture the shell from inside the imported simulation program leads to the program crashing.

Does anybody have any ideas about how I can best achieve this? So all I really need is for all console text to be captured by a TextCtrl while the GUI remains responsive, and all text is solely coming from an imported module.

(Also, secondary question regarding a Stop button - is it bad form to just kill the simulation thread?).

Thanks,

Duncan

  • I would suggest posting an actual separate question for your inquiry about the stop button. This isn't a forum so it's best to post different questions separately. – Soviut Nov 16 '12 at 11:24

2 Answers2

0

I would suggest looking into this WX wiki article about long running tasks.

It specifically addresses the situation you're dealing with using a "start" button to being a long running process. Several different examples are given using different techniques like threads and idle handlers.

Soviut
  • 88,194
  • 49
  • 192
  • 260
-1

I think you would have to redirect stdout to a log file (or simple SQLite database?) and then use your thread to check the log file for updates which it would then pass along to the GUI using wx.CallAfter or similar. You might be able to use something like a socket server built in Python: http://wiki.wxpython.org/AsynchronousSockets. I think the wxPython Cookbook mentioned something about using an RPC server too (probably this one: http://docs.python.org/library/simplexmlrpcserver.html), but I don't remember the details.

You should also try asking on the official wxPython mailing list. They're very friendly over there.

Mike Driscoll
  • 32,629
  • 8
  • 45
  • 88