views:

155

answers:

1

I'm relatively new to wxPython (but not Python itself), so forgive me if I've missed something here.

I'm writing a GUI application, which at a very basic level consists of "Start" and "Stop" buttons that start and stop a thread. This thread is an infinite loop, which only ends when the thread is stopped. The loop generates messages, which at the moment are just output using print.

The GUI class and the infinite loop (using threading.Thread as a subclass) are held in separate files. What is the best way to get the thread to push an update to something like a TextCtrl in the GUI? I've been playing around with PostEvent and Queue, but without much luck.

Here's some bare bones code, with portions removed to keep it concise:

main_frame.py

import wx
from loop import Loop

class MainFrame(wx.Frame):
  def __init__(self, parent, title):
    # Initialise and show GUI
    # Add two buttons, btnStart and btnStop
    # Bind the two buttons to the following two methods
    self.threads = []
  def onStart(self):
    x = Loop()
    x.start()
    self.threads.append(x)
  def onStop(self):
    for t in self.threads:
      t.stop()

loop.py

class Loop(threading.Thread):
  def __init__(self):
    self._stop = threading.Event()
  def run(self):
    while not self._stop.isSet():
      print datetime.date.today()
  def stop(self):
    self._stop.set()

I did, at one point, have it working by having the classes in the same file by using wx.lib.newevent.NewEvent() along these lines. If anyone could point me in the right direction, that'd be much appreciated.

+1  A: 

The easiest solution would be to use wx.CallAfter

wx.CallAfter(text_control.SetValue, "some_text")

You can call CallAfter from any thread and the function that you pass it to be called will be called from the main thread.

Toni Ruža
+1, this is the simplest way which works.
Anurag Uniyal
Thank you. I'm assuming that my thread will need to be passed a window (ie. `self` in `MainFrame`) so that I can call `wx.CallAfter(self.window.text_control.SetValue.SetValue, "some_text")` in the `Loop` class?
Sam Starling
@sam Yes, you will need access to controls you wish to modify. One way to accomplish this (as good as any other) is to pass the window to the thread.
Toni Ruža