FAQ Index - Search - Recent Changes - Everything - Add entry

<< Previous Entry | FAQ Entry 10.13 | Next Entry >>

10.13. When closing the GnomeAbout box (or other GtkDialog subclasses), I get crashes and weird callback behaviour. What up with that?

Normally, when handling closed signals on a window, you should follow the advice in FAQ 10.6. However, for GnomeAbout, things aren't so simple.

Jon Willeke took the time to point out that in the case of GnomeAbout, to avoid having a window be destroyed when you close it, you need to also connect to the "response" handler. Malcolm Tredinnick offered a more detailed explanation of how this works:

A GtkDialog box has two main signals it implements: 'close' and 'response'. It also inherits the 'delete-event' signal from the GtkWidget class which also has a role to play here.

The 'response' signal is emitted pretty much whenever any action happens that causes the dialog box to finish running. The response signal emission will contain a "response ID" which can be user-defined or any one of the gtk.RESPONSE_* constants in pyGTK. The standard values correspond to things like one of the standard buttons being pushed or the window being destroyed. You can act differently based on the response ID.

The 'delete' signal is emitted whenever the corresponding GtkWidget is deleted in a "strange" (for want of a better word) way. The main case here is when the user closes the window via the window manager (Alt-F4, or clicking on the 'X' button in a typical window manager, for example). In that case, you also get a 'response' signal, so generally you just ignore the 'delete' signal (return gtk.TRUE as has been mentioned elsewhere).

For your standard GtkDialog widget, the only way the 'close' signal is emitted is when the Escape key is pressed. Widgets deriving from GtkDialog may have other buttons that are hooked up to emit 'close', but by default it is only bound to the Escape key (try it and see for the About dialog -- you can close it with Escape and it emits the predicted signal).

Colin Fox posted a summary of the signals he had to connect and the methods he needed to define to make things work as expected:

  def __init__(self, *args):
      # ...
      self.connect("response", on_aboutbox_response)
      self.connect("close", on_aboutbox_close)
      self.connect("delete_event", on_aboutbox_close)

  def on_aboutbox_response(self, dialog, response, *args):
      # system-defined GtkDialog responses are always negative, in which    
      # case we want to hide it
      if response < 0:
        dialog.hide()
        dialog.emit_stop_by_name('response')

  def on_aboutbox_close(self, widget, event=None):
      self.aboutbox.hide()
      return gtk.TRUE
In short, to keep the dialog from destroying itself or crashing you need to define a "delete-event" handler that returns True and define a "response" handler that stops emission of the signal, and, if you want the Escape key to work as expected, you also need to connect to the close signal.

It remains to be seen why you have to emit_stop_by_name() in the response handler -- it might be a GTK+ bug, but nobody alive seems to know the answer.

PyGTK FAQ Wizard | PyGTK Homepage | Feedback to faq at pygtk.org