Search code examples
cgtkgtk4

GTK4 Window Created from XML, Closes Immediately After Run()


Based on the documentation, it seems the window should stay open as long as "g_application_run" is used, and a reference increment is performed. Since I do this, I'm not sure what I'm doing wrong that causes the GUI to display yet immediately close:

 GtkBuilder* myGtkBuilder;
 GtkWidget* myGtkWindow;
 GtkApplication* myGtkApp;
 
 // Since we will be using an xml design file, the passed 'app' parameter won't be used 
 static void activate_cb(GtkApplication* app, gpointer user_data) {
    
     // Load the UI from the XML file
     myGtkBuilder = gtk_builder_new_from_file("gtk4.glade");
 
     // Get the window widget from the builder
     myGtkWindow = GTK_WIDGET(gtk_builder_get_object(myGtkBuilder, "window"));
 
     // (Optional) Connect signals to the GUI elements here if needed
 
     // Show the window without using gtk_widget_set_visible(myGtkWindow, true);
     gtk_window_present(GTK_WINDOW(myGtkWindow));
     g_object_ref(myGtkWindow); // Increase reference count
 
     // Clean up resources
     g_object_unref(myGtkBuilder);
 }
 
 
 int main(int argc, char *argv[]) 
 { 
     int status;
     GError* error = NULL;
     
     gtk_init(&argc, &argv);  // Needed?
 
     myGtkApp = gtk_application_new("myAppId.id", G_APPLICATION_DEFAULT_FLAGS);  // vs gtk_application_window_new?  G_APPLICATION_DEFAULT_FLAGS vs G_APPLICATION_FLAGS_NONE
     g_signal_connect(myGtkApp, "activate", G_CALLBACK(activate_cb), NULL);
     status = g_application_run(G_APPLICATION(myGtkApp), argc, argv);
 
     // Free resources
     g_object_unref(myGtkApp);
 
     return status;
 }

I've tried several XML files, all behave the same:

 <?xml version="1.0"?>
 <interface>
   <object class="GtkWindow" id="window">
     <property name="title">Checkboxes Example</property>
     <child>
       <object class="GtkBox" id="box">
         <property name="orientation">GTK_ORIENTATION_VERTICAL</property>
         <child>
           <object class="GtkCheckButton" id="checkbox1">
             <property name="label">Checkbox 1</property>
           </object>
         </child>
         <child>
           <object class="GtkCheckButton" id="checkbox2">
             <property name="label">Checkbox 2</property>
           </object>
         </child>
       </object>
     </child>
   </object>
 </interface>

Unfortunately, the 2 other similar questions on SO didn't work for me (python instead of c)


Solution

  • Quote from the documentation:

    "GTK 4 removes the gtk_main_* family of APIs. The recommended replacement is GtkApplication. ... Currently, GtkApplication handles GTK initialization, application uniqueness, session management, provides some basic scriptability and desktop shell integration by exporting actions and menus and manages a list of toplevel windows whose life-cycle is automatically tied to the life-cycle of your application."

    Your problem is that you don't have a window connected to the application. So your application has nothing to do and that's why it closes straight away.

    The following simple example shows how it can work.

    #include <gtk/gtk.h>
    
    static void
    activate (GtkApplication* app,
              gpointer        user_data)
    {
      GtkWidget *window;
    
      window = gtk_application_window_new (app);
      gtk_widget_set_visible(window,TRUE);
    }
    
    int
    main (int    argc,
          char **argv)
    {
      GtkApplication *app;
      int status;
    
      app = gtk_application_new ("holger.gtk.simpleexample", G_APPLICATION_DEFAULT_FLAGS);
      g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
      status = g_application_run (G_APPLICATION (app), argc, argv);
      g_object_unref (app);
    
      return status;
    }
    

    Of course, you could also write your own window class using the builder and then connect this class to the application. You can find an example here.

    Create your own class from a template with GTK4, C and XML