pygtk glib.timeout_add(): 如何判断计时器没有被销毁?
在我的应用程序中,我使用一个函数来显示GtkInfoBars,并设置一个超时(具体方法可以参考这个链接),这是通过glib.timeout_add_seconds()实现的。
我明白glib.timeout_add_seconds()的作用是定期调用一个函数,直到这个函数返回False为止。
不过我并没有这样做,但一切都按预期运行,感觉非常简单。以下是我的代码:
def infobar(self, message, msgtype=gtk.MESSAGE_INFO, timeout=5):
bar = gtk.InfoBar()
bar.set_message_type(msgtype)
bar.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)
bar.connect("response", lambda *args: bar.hide())
self.vb2.pack_end(bar, False, False)
label = gtk.Label()
label.set_markup(message)
content = bar.get_content_area()
content.add(label)
label.show()
bar.show()
if timeout:
glib.timeout_add_seconds(timeout, bar.hide)
那么,问题来了。看看我在最后一行做的事情。简单来说,这样做可以吗?当第二次调用bar.hide()失败时,超时会自己消失吗?还是说我在不断增加一些无用的超时,它们每5秒会“醒来”一次,实际上会消耗资源呢?
补充说明:
如果我猜的没错,这样做是不好的,我确实需要返回False来销毁这些超时,那么我需要一些帮助——我搞不清楚该如何调整代码,以满足以下条件:我需要同时允许多个InfoBars存在,每个InfoBar都能保持与自己的计时器和按钮响应信号连接(就像现在的代码那样) 或者 我需要每个新的InfoBar替换掉之前的那个(我不知道该如何做到这一点,而不让新的InfoBar继承之前的计时器——这样会变得很麻烦)。
谢谢你的阅读!
2 个回答
关于 bar.hide
被调用多次的问题,我觉得这应该不会发生。因为据我所知,只要返回一个被认为是 False
的值就可以了,而 bar.hide
返回的是 None
,这应该就足够了。不过,如果你想完全确认一下,可以用下面的方式来验证:
import gtk, glib
def callback():
print 'called'
glib.timeout_add_seconds(1, callback)
gtk.main()
在这个例子中,回调函数也返回 None
,而且从输出到 stdout
可以看到,它只被调用了一次。
至于你最后的问题,我觉得这种方式已经可以接受了,可以让多个信息条每个都有自己的计时器。如果我漏掉了什么,请补充更多信息。
Widget.hide
这个方法总是返回 None,而 glib.timeout_add_seconds
会把它当成 False 来处理。所以,你的计时器每次运行后都会结束。虽然有可能 hide
会被调用两次(比如用户点击确定和在 5 秒超时后),但这没关系。所以,你的代码是没问题的。
编辑:我刚意识到一点。你每次函数运行时都在创建一个新的信息条,然后只是把它隐藏起来。与其用 hide
,不如用 destroy
,这样可以把它彻底清理掉。
...或者我需要让每个新的信息条替换掉之前的那个(我不知道怎么做,不想让新的计时器继承之前的信息条的计时器,这样会变得很麻烦)。
其实这并不复杂;只需重复使用同一个信息条即可。记录下 glib.timeout_add_seconds
的返回值,然后在替换信息条的内容时,用 glib.source_remove
来结束之前的计时器。
你提到的这两种选择之间有可用性上的权衡(干净的用户界面 vs. 确保用户不会错过重要信息),但这是另一个话题,也许不是那么重要。