wxPython 忽略或删除事件

0 投票
3 回答
2206 浏览
提问于 2025-04-18 10:39

我的程序有几个按钮,当点击这些按钮时,会调用一些需要花费一点时间才能完成的函数。现在遇到的问题是,有时候一个按钮会“激活”两次,导致这个函数不明原因地被执行了第二次。而且,由于这些函数运行时间较长,用户在第一个函数还在运行的时候,可能会多次点击同一个按钮,或者点击其他按钮,这样的话,其他按钮的函数会在第一个函数完成后立刻执行。

我想要做的是能够丢弃任何待处理的事件,这样这些按钮就不会重复激活,也能防止用户不小心排队执行一堆这些函数。我想我也可以在一个按钮被点击后立刻禁用所有按钮,但相比于直接清空事件队列,这种方法看起来就不太优雅。

我到处查找,似乎有一些可以实现我想要功能的函数,但我就是不知道怎么调用它。当然,也有可能我用的wxPython版本里没有这个函数,不太确定这是否可能。

谢谢

3 个回答

0

你可能应该这样做(记住,这只是一个非常简单的例子)

import wx ,time
import threading
def the_actual_long_task(whatever=None):
    for i in range(15):
        time.sleep(1)
        print "TASK RUNNING!"
     return whatever
my_lock = threading.Lock()
def long_task(callback,some_other_arg=None):
    my_lock.acquire() #this will block until the lock is released by another thread
    my_return_value = the_actual_long_task(some_other_arg) 
    wx.CallAfter(callback,my_return_value)
    my_lock.release() #allow another thread to acquire the lock
def OnTaskDone(result):
    print "Task Done!",result
    my_button.Enable(True)
    my_button.SetLabel("Run Task")
def OnButton(event):
    t = threading.Thread(target=long_task,args=(OnTaskDone,))
    t.start()
    my_button.Enable(False)
    my_button.SetLabel("Test In Progress...")
a = wx.App(redirect = False)
f = wx.Frame(None,-1,"Example")
my_button = wx.Button(f,-1,"Run Task",size=(200,-1))
my_button.Bind(wx.EVT_BUTTON,OnButton)
f.Show()
a.MainLoop()

使用线程来运行任务可以让你的界面不被阻塞

禁用按钮会让它在任务完成之前无法再次点击

0

正如其他人已经提到的,简单的解决办法就是在长时间运行的任务完成之前,先把按钮禁用掉。这样就不会再接受其他的按钮点击了。另一方面,你也可以在事件处理函数里调用按钮的 Unbind() 方法,把事件处理器从按钮上移除。

类似这样的代码应该可以工作:

def myEventHandler(self, event):
    self.ButtonOne.Unbind(wx.EVT_BUTTON, self.myEventHandler)

另外,你可以参考以下链接:

1

当你按下一个按钮时,你可以试着把想要停止事件的窗口的 SetEvtHandlerEnabled 方法设置为 false,这样就可以停止事件的处理。等事情完成后,再把它设置回 true。

撰写回答