1

I'm creating a program that keeps checking for change in a MySQL database, and according updates a GTK display. The part that keeps checking is in an infinite loop.

What I want is that once the GTK window has been closed, I can break out of the infinite loop.

But I don't know what condition to use for that. I've tried

if !window:

and

if window == None:

but in either case, it doesn't work.

The structure of my code is like this:

while True:

    # my code

    while gtk.events_pending():
         gtk.main_iteration()

    # something to exit here

window.connect("destroy", gtk.main_quit())

I don't know if placing "window.connect" there can cause a problem, because the window seems to close just fine. Also, if I placed it within the loop, or before the loop, I'd get a Runtime Error: called outside of mainloop.

So to re-iterate, how do I exit the infinite loop using the closure of the window as a condition? I don't want the user to have to use Ctrl + C.

Thanks in advance!

Antimony
  • 2,230
  • 3
  • 28
  • 38

2 Answers2

1

This is a classical background thread problem. You need to have a loop like this:

closing = False

while not closing:
    // do the MySQL stuff

And then connect a signal handler to window destroy event that sets closing to True

anttix
  • 7,709
  • 1
  • 24
  • 25
  • Thanks, but how do I do that? I've already connected the window destroy event to the gtk.main_quit event. – Antimony Jul 26 '12 at 20:02
  • Create your own handler and call gtk.main_quit from there. However I think the solution proposed by unutbu is architecturally much better since in this case GTK will handle the main loop of your program – anttix Jul 26 '12 at 20:46
  • The way I implemented unutbu's solution, it didn't work for me. Can you suggest something I might be missing? (I left a comment under his solution) – Antimony Jul 26 '12 at 20:49
0

The basic structure of a pygtk app is usually something like this:

win = gtk.MyWindow()
win.connect("destroy", gtk.main_quit)  # Note no paretheses after main_quit. 
gobject.timeout_add(1000, win.check_DB)  
win.show_all()
gtk.main()

The gobject.timeout_add command will call the win.check_DB method every 1000 milliseconds.


In win.connect("destroy", gtk.main_quit) it is important not to put parentheses after main_quit. You are passing the function object gtk.main_quit to the win.connect method, not the return value of having called gtk.main_quit(), which is what would happen if you add the parentheses.

Since gtk.main_quit() quits the app, using parentheses here halts the program too early.

unutbu
  • 842,883
  • 184
  • 1,785
  • 1,677
  • I tried this. I made a function called check_DB. Firstly I tried calling it like this: gobject.timeout_add(1000, check_DB) but that didn't seem to be working. I don't want to have to repeatedly make the connection to the MySQL database, so I don't want to perform that bit inside the function. However, I can't pass the connection variable to check_Db either. Help? – Antimony Jul 26 '12 at 20:11
  • To keep things simple, I would make the connection object a global variable. http://stackoverflow.com/questions/423379/using-global-variables-in-a-function-other-than-the-one-that-created-them – anttix Jul 26 '12 at 20:57
  • @Antimony: If you set `win.connection = MySQLdb.connect(...)` in `MyWindow.__init__`, then you can use it when `win.check_DB` is called. Or, like @anttix suggests, you could make the connection a global variable. – unutbu Jul 26 '12 at 21:04
  • I don't have a MyWindow.__init__. No OOP in this code, it's all procedural. Adding it after win = gtk.Window() throws this error: AttributeError: 'gtk.Window' object has no attribute 'check_DB'.@anttix: The part that handles the connection is inside a try ... except block. So I can't make it global. I put the function inside the try ... except block, but nope, nothing. Right now I haven't even put the bit that updates the GUI, all it's doing is displaying the changed value of the database. But it doesn't do that here. – Antimony Jul 26 '12 at 21:19
  • @Antimony: Put `global conn` at the top of the function that creates the connection. `conn` will then be a global variable. It matters not that `conn = MySQLdb.connect(...)` occurs inside a try..except block. – unutbu Jul 26 '12 at 21:28
  • Ohh! It works! [Here's](http://stackoverflow.com/questions/6072639/interacting-with-a-gtk-container-while-gtk-main-is-executing) the little thing that I was missing! Thanks both of you! :D – Antimony Jul 26 '12 at 21:36