Cannot present dialog multiple times - "assertion 'GTK_IS_WINDOW (window)' failed"

Hi all,
I am currently getting into developing GUIs with Python, GTK4 and libadwaita.
So far, my experience has been quite nice, but now I am hitting a problem:
When I create a AdwDialog, I can open it once, but if I close it and try to reopen it I get the following Error message:

(python3:45276): Gtk-CRITICAL **: 09:46:38.651: gtk_window_present: assertion 'GTK_IS_WINDOW (window)' failed

Here’s a minimal (non-) working example for this behavior:

import gi                                                                                                                                                                           
gi.require_version('Gtk', '4.0')                                                                                                                                                    
gi.require_version('Adw', '1')                                                                                                                                                      
                                                                                                                                                                                    
from gi.repository import Gtk, Adw                                                                                                                                                  
                                                                                                                                                                                    
class DemoWindow(Gtk.ApplicationWindow):                                                                                                                                            
    def __init__(self, **kwargs):                                                                                                                                                   
        super().__init__(**kwargs)                                                                                                                                                  
        self.set_title("Dialog Example")                                                                                                                                            
        self.set_default_size(200, 100)                                                                                                                                             
                                                                                                                                                                                    
        self.dialog = Adw.Dialog(title="Dialog Example", parent=self)                                                                                                               
        self.closebtn = Gtk.Button(label="Close")                                                                                                                                   
        self.closebtn.connect("clicked", self.on_close_clicked)                                                                                                                     
        self.dialog.set_child(self.closebtn)                                                                                                                                        
        button = Gtk.Button(label="Open Dialog")                                                                                                                                    
        button.connect("clicked", self.on_button_clicked)                                                                                                                           
        self.set_child(button)                                                                                                                                                      
                                                                                                                                                                                    
    def on_button_clicked(self, button):                                                                                                                                            
        self.dialog.present(self.get_root())                                                                                                                                        
                                                                                                                                                                                    
    def on_close_clicked(self, button):                                                                                                                                             
        self.dialog.close()                                                                                                                                                         
                                                                                                                                                                                    
class DemoApp(Adw.Application):                                                                                                                                                     
    def __init__(self):                                                                                                                                                             
        super().__init__(application_id="org.example.demoapp")                                                                                                                      
        self.connect("activate", self.on_activate)                                                                                                                                  
                                                                                                                                                                                    
    def on_activate(self, app):                                                                                                                                                     
        self.win = DemoWindow(application=app)                                                                                                                                      
        self.win.present()                                                                                                                                                          
                                                                                                                                                                                    
if __name__ == "__main__":                                                                                                                                                          
    DemoApp().run()

What am I doing wrong? Greatly appreciate your help

- Jens

Hi,

Hmm… I think dialog.close() will destroy the dialog widget, so you can’t reuse it afterwards.

Either recreate the dialog (e.g. in on_button_clicked), or use hide() instead of close().

AdwDialog needs an AdwApplicationWindow / AdwWindow

Second - same as with any other widget that’s nto a window, if you want to unparent and parent it again you have to keep a reference to it yourself. I don’t know how to do it in Python, in C you just call g_object_ref()

hide() is deprecated and even if it wasn’t would not do anything good with a dialog

1 Like

In Python, using an attribute like self.dialog will keep a reference as long as the object (ApplicationWindow here) is referenced too. So should be fine here.

Ah, thanks for the tip!

Seems to be the real issue here :slight_smile:
When not using an AdwWindow, the adw_dialog_close will be forwarded to gtk_window_close which will call destroy().

Ah, good point and ig we never create a new one.

dialog: Unset internal window after closing it (!1324) · Merge requests · GNOME / libadwaita · GitLab might help

1 Like