wxpython事件不触发

0 投票
2 回答
861 浏览
提问于 2025-04-17 03:25

我正在按照这个链接里的例子进行操作:http://www.blog.pythonlibrary.org/2010/05/22/wxpython-and-threads/

我有一个线程,每30秒检查一次sftp服务器,看有没有新文件。如果找到文件,它会把这些文件上传到数据库,然后应该更新某些图形界面(GUI)元素,这些元素会从数据库重新加载数据。

这是自定义事件的代码:

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

这是ftp线程的代码:

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"))

这是其中一个图形界面元素的代码:

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):
    ...

经过调试,我发现wx.PostEvent这个事件确实被创建了,但在表格中没有任何反应。

我能找到的唯一不同之处是,例子中的EVT_RESULT是在主框架里,而不是在某个图形界面元素里——这是必须的吗?

2 个回答

0

我不太确定,但那个例子是基于维基上的一些内容:http://wiki.wxpython.org/LongRunningTasks

我猜因为它提到“win”作为一个参数,可能是指一个顶层窗口,所以可能需要用到wx.Frame。不过你还是可以从这个框架中更新网格。

编辑:Manny说得对。那样也可能有效。而且pubsub真不错!

1

事件不会传递给它的子元素,所以如果 MyGrid 是你主窗口的一个子元素,主窗口中的事件不会传递到 MyGrid。你可以做的是直接把事件处理函数绑定到 MyGrid 的实例上,像这样:

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

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

我对这种绑定方式不太熟悉,因为我通常使用 wx.Bind。

撰写回答