0

I'm following the example given in http://www.blog.pythonlibrary.org/2010/05/22/wxpython-and-threads/

I have a thread which is checking an sftp server for new files every 30 seconds. If it finds files, it uploads them to a db, and then it should trigger an update of certain GUI elements which will reload from the db.

The custom event code:

EVT_RESULT_ID = wx.NewId()

def EVT_RESULT(win, func):
    """Define Result Event."""
    win.Connect(-1, -1, EVT_RESULT_ID, func)

class ResultEvent(wx.PyEvent):
    """Simple event to carry arbitrary result data."""
    def __init__(self, data):
        """Init Result Event."""
        wx.PyEvent.__init__(self)
        self.SetEventType(EVT_RESULT_ID)
        self.data = data

The ftp thread:

class FTPThread(threading.Thread):
def __init__(self,wxObject):
    """Init Worker Thread Class."""
    threading.Thread.__init__(self)
    self.wxObject = wxObject
    self._stop = threading.Event()
    self._stop.set()
    self.start()    # start the thread

def run(self):
    while True:
        time.sleep(30)
        if not self._stop.isSet():
            wx.CallAfter(self.parseFTP)

def stop(self):
    self._stop.set()

def resume(self):
    self._stop.clear()

def parseFTP(self):
    #connect to db
    ...

    #connect to sftp site
    ...
    files_found=False

    #process each file and delete
    for file in dirlist:
        files_found=True
        ...#process into db
        sftp.remove(file)
    sftp.close()
    t.close()

    #trigger update event if files found
    if files_found==True:
        wx.PostEvent(self.wxObject, ResultEvent("Files found"))

One of the GUI elements:

class MyGrid(wx.grid.Grid):
def __init__(self, parent):
    wx.grid.Grid.__init__(self, parent,-1,style=wx.EXPAND)
    self.parent=parent
    ...
    self.update()
    EVT_RESULT(self, self.updateFromEvent)

def updateFromEvent(self,event):
    self.update()

def update(self):
    ...

Following debugging, the wx.PostEvent is being created, but not triggering any response in the grid.

The only difference I can find between the example and my code is that in the example the EVT_RESULT is in the main Frame, and not a GUI element - is this required?

2 Answers 2

1

Events don't propagate to its children so if MyGrid is a child of your main frame, events posted in the main won't make it through to MyGrid. What you can do instead is bind the event handler directly to your function within the instance of MyGrid like so:

"""from MainWindow"""
self._workerthread = FtpThread(...)
self._mygrid = MyGrid(...)

# Bind event
EVT_RESULT(self, self._mygrid.updateFromEvent)

I'm not too familiar with this kind of binding as I typically use wx.Bind.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks. In the end I've found that use of libPubSub wiki.wxpython.org/WxLibPubSub is more 'correct' for what I'm trying to do than using Events, and I've got it working that way.
0

I'm not sure, but that example was based on something in the wiki: http://wiki.wxpython.org/LongRunningTasks

I suspect that since it says "win" as an argument, it is probably referring to a Top Level Window, so the wx.Frame is probably required. You can still update the grid from the frame though.

EDIT: Manny has a good point. That would probably work too. And pubsub rocks!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.