pygtk glib.timeout_add(): How to tell if timer not being destroyed?

梦想的初衷 提交于 2019-12-10 15:57:35

问题


In my application I use a function to show GtkInfoBars with a timeout (as described https://stackoverflow.com/a/1309257/406281) thanks to glib.timeout_add_seconds().

I understand that glib.timeout_add_seconds() is supposed to set a function to be called at regular intervals until said function returns False.

I'm not doing that, but everything works as expected. It's perfectly simple. Here's my code:

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)

SO. Question time. Look at what I did in the last line. Simply put, is this okay? Will the timeout destroy itself after the second call to bar.hide() fails? Or am I accumulating extra neutered timeouts that will wake up every 5 seconds [technically] using up resources?


As an addendum:

If, as I suspect, this is bad, and I really do need to return False to destroy the timeouts, I need some help -- I can't figure out how to play around with the code in order to satisfy these conditions: I need to allow multiple InfoBars at the same time, with each still staying connected to their own timer and button-response signal (as the code is now) OR I need each new InfoBar to replace any previous one (I can't figure out how to do this without inheriting the timer from the previous InfoBar--it gets messy).

Thanks for reading!


回答1:


Widget.hide always returns None, which glib.timeout_add_seconds treats identically to False. Thus, your timer will always terminate after running once. There is a possibility that hide will be called twice (when the user clicks OK and at the 5 s timeout) but that's alright. So yes, your code is fine.

Edit: Just realised something. You're creating a new info bar every time the function runs, then only hiding it. Instead of using hide, use destroy so it gets properly cleaned up.

... OR I need each new InfoBar to replace any previous one (I can't figure out how to do this without inheriting the timer from the previous InfoBar--it gets messy).

It's not too complicated; just reuse the same info bar. Record the return value of glib.timeout_add_seconds, then while replacing the content of the info bar, kill the previous timer with glib.source_remove.

There are usability trade-offs between the two choices you present (clean UI vs. making sure the user doesn't miss important info) but that's another topic and perhaps not that important.




回答2:


Regarding bar.hide being called more than once, I think that's not happening because, as far as I know, it should be enough to return a value that is evaluated as False and bar.hide returns None which should be enough. However, if you want to make completely sure, you can verify with something like this:

import gtk, glib

def callback():
    print 'called'

glib.timeout_add_seconds(1, callback)
gtk.main()

In this example, the callback returns None as well and is called just once as you can see from the output to stdout.

Regarding your final question, I'd say this is already an acceptable way of having multiple infobars with a separate timer for each one. Please add more information if I'm missing something.



来源:https://stackoverflow.com/questions/8982843/pygtk-glib-timeout-add-how-to-tell-if-timer-not-being-destroyed

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!