0

I am new to GTK and I stumbled upon a problem which sounds simple but I just can't find a way to deal with it. Basically, calling gtk.main() makes my single-threaded process halt. I know that gtk.main() is blocking, but I have not called gtk.main() any time before so quitting the main loop will not do any good since there is no loop to quit from.

Even so, gtk.main_level() returns 0. Moreover, when I try gtk.main() from the python command line, it hangs as well. There is something basic I am missing, so can anybody point me to it? Appreciated.

EDIT: The Gtk method I need is gobject.add_timeout, like this:

gobject.timeout_add(2000, callback)
gtk.main() # This blocks the thread.
gpoo
  • 8,408
  • 3
  • 38
  • 53
zpavlinovic
  • 1,507
  • 1
  • 17
  • 36
  • create a frame or window first and show it ... then call main... – Joran Beasley Oct 17 '12 at 05:54
  • Actually, I am not using windows. I just want to set timeout. I updated my post. – zpavlinovic Oct 17 '12 at 06:05
  • I don't understand the problem: you say that `gtk.main` is blocking and it blocks... what do you want to do, exactly? And what are you not getting? Is the timeout not running? If so, what is the declaration of `callback`? – rodrigo Oct 17 '12 at 06:29
  • If I don't call the gtk.main, the timeout_add has no effect. If I call it, I can see the handler triggered since it prints out some bogus stuff. The problem is that gtk.main() hangs and I would like it not to hang. – zpavlinovic Oct 17 '12 at 07:01
  • do you have a callback function? are you sure its not getting called? – Joran Beasley Oct 17 '12 at 14:29
  • its not hanging ... its an event loop that runs forever handling typically window type events... you need to exit the loop wiith gtk.quit or whatever ... – Joran Beasley Oct 17 '12 at 14:30

2 Answers2

8

It looks like it is blocking the application, but what is doing is processing events. One of the events has to terminate the loop. You can check the idea behind the event loops in Wikipedia.

If you do not want to program a graphical interface, then you do not need Gtk, you only need Glib. Here an example to show you how the main loop works (the concept is similar in Gtk and Glib):

from gi.repository import GLib, GObject

counter = 0

def callback(*args):
    global counter
    counter += 1
    print 'callback called', counter
    if counter > 10:
        print 'last call'
        return False

    return True

def terminate(*args):
    print 'Bye bye'
    loop.quit()

GObject.timeout_add(100, callback)
GObject.timeout_add(3000, terminate)
loop = GLib.MainLoop()
loop.run()

If the callback returns False, then it will be removed and not called anymore. If you want the callback to be called again, it has to return True (as you can see in the function callback).

I set another callback terminate to show how to quit from the loop. If you do not do it explicitly, then GLib will continue waiting for more events (It does not have any way to know what you want to do).

With the PyGTK (old and deprecated), the code will be:

import gobject, glib, gtk

counter = 0

def callback(*args):
    global counter
    counter += 1
    print 'callback called', counter
    if counter > 10:
        print 'last call'
        return False

    return True

def terminate(*args):
    print 'Bye bye'
    loop.quit()

gobject.timeout_add(100, callback)
gobject.timeout_add(3000, terminate)
loop = glib.MainLoop()
loop.run()
gpoo
  • 8,408
  • 3
  • 38
  • 53
  • 1
    +1 for the nice examples. I would add that the first one is based on the "GObjectIntrospection" implemented with GTK3, you can find further explanations [here](https://live.gnome.org/GObjectIntrospection) and for python [here](https://python-gtk-3-tutorial.readthedocs.org/en/latest/index.html). – Zoé Martin Oct 17 '12 at 07:34
0

I encountered the same problem then I add this gtk.gdk.threads_init() before call gtk.mainloop(). It works fine with me

tset0401
  • 25
  • 8