Main loop quit from message dialog?

I want to do a main quit after pressing a button from a message dialog such as:

dialog = Gtk.MessageDialog(
    flags=0,
    message_type=Gtk.MessageType.INFO,
    buttons=Gtk.ButtonsType.OK,
)

response = dialog.run()
if response == Gtk.ResponseType.OK:
    # *** do_close()
    Gtk.main_quit()

dialog.destroy()

With plain Gtk.main_quit(), I get the following error message:

Gtk-CRITICAL **: 16:58:16.035: gtk_main_quit: assertion 'main_loops != NULL' failed

I guess I need to close, finish or quit the message dialog first, but how can I do this?

Many thanks for your help.

Are you using Gtk.main()? If not, you can’t use Gtk.main_quit(). For example, you may (and should) be using GtkApplication instead.

Side note: gtk_dialog_run() uses a recursive main loop. This API is no longer recommended, and has been removed in GTK4. Instead, you can connect to the response signal and (optionally) make the dialog modal. That also works in GTK3.

Many thanks for your reply, @chrisaw.

Are you using Gtk.main()? If not, you can’t use Gtk.main_quit(). For example, you may (and should) be using GtkApplication instead.

I use Gtk.main() and Gtk.main_quit() works fine in other places of the script.

Side note: gtk_dialog_run() uses a recursive main loop. This API is no longer recommended, and has been removed in GTK4. Instead, you can connect to the response signal and (optionally) make the dialog modal. That also works in GTK3.

Sorry, I’m afraid coding is hard for me. Not sure if this demo is what you meant.

button.connect("clicked", self.on_clicked_button) would be the way to go, but I have no idea how to name the button in the previous dialog sample (I mean, I don’t know its variable name).

My case is the opposite as the one from the example. I need to connect from a button in a dialog, not to it (if I’m not getting this wrong :sweat_smile:).

Many thanks for your help.

In that case, the only way I can think that would happen is if you call Gtk.main_quit() again after the main loop has already returned.


Using the dialog without run() would look something like this:

def on_dialog_response(dialog, response):
    if response == Gtk.ResponseType.OK:
        Gtk.main_quit() 

def show_dialog():
    dialog = Gtk.MessageDialog(
        modal=True,
        message_type=Gtk.MessageType.INFO,
        buttons=Gtk.ButtonsType.OK,
    )
    
    dialog.connect('response', on_dialog_response)
    
    dialog.present()

BTW, OK buttons are discouraged by the GNOME HIG. It’s better to use a verb, e.g. ‘Close’. Also, for a dialog with only one button, closing the dialog via the Esc key (or the X, if present) should have the same result as clicking that button.

Many thanks for your help, @chrisaw.

This worked perfectly fine and now I know how to avoid the loop.

I also replaced the button type from OK to CLOSE (it makes more sense).

In due time, I think I will have to move this script to GTK+4.

Hippocrates once said «ὁ βίος βραχὺς, ἡ δὲ τέχνη μακρὴ…» (“life is short, and art long”).
.
Many thanks again for your help.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.