Search code examples
c++gtkgtkmm3

Gtk::Window add grid is not showing my child widgets


I attached two widgets to a grid; a label and a spinbutton, then added the grid to Gtk::Window

I get blank output like this:

Screenshot of window

#include <gtkmm.h>

class SpinButtonExample : public Gtk::Window {
public:
    SpinButtonExample();
};

SpinButtonExample::SpinButtonExample()
{
    auto grid       = Gtk::Grid();
    auto label      = Gtk::Label("Hi!");
    auto adjustment = Gtk::Adjustment::create(0, 0, 10);
    auto spinbutton = Gtk::SpinButton(adjustment);

    grid.set_column_homogeneous(true);
    grid.attach(label     , 0, 0, 1, 1);
    grid.attach(spinbutton, 1, 0, 1, 1);

    add(grid);

    show_all();
}

int main()
{
    auto application = Gtk::Application::create("test.focus.spinbutton");

    SpinButtonExample test;

    return application->run(test);
}

However, if I use glade file it works fine but I want to do it with code and I'm stuck...


Solution

  • Since your grid variable (and all the others) are local variables, they're destroyed once SpinButtonExample::SpinButtonExample() finishes.

    This is not specific to GTK, it's a C++ memory management issue. Local variables are destroyed at the end of their scopes.

    You need a way to keep a reference to your widgets after the constructor finishes. The simplest way to do that is to declare grid as a class member. This way it will exist as long as the containing class exists.

    You can also use new to dynamically allocate memory for an object, but then you'll need to delete the pointer to avoid a memory leak. And you'll need to store the pointer anyway.

    For child widgets you can dynamically allocate them and have them destroyed when their parent object is destroyed using Gtk::make_managed. I've done that with spinbutton in the example below to show the basic idea.

    Which is the best way dependes on the circustances.

    Here's an updated version of your code, showing some of the ways to keep a reference to the widgets:

    #include <gtkmm.h>
    
    class SpinButtonExample : public Gtk::Window {
    public:
        SpinButtonExample();
    
    private:
        Gtk::Grid grid;
        Gtk::Label label;
    };
    
    SpinButtonExample::SpinButtonExample()
      : grid()
      , label("Hi!")
    {
        auto adjustment = Gtk::Adjustment::create(0, 0, 10);
        auto spinbutton = Gtk::make_managed<Gtk::SpinButton>(adjustment);
    
        grid.set_column_homogeneous(true);
        grid.attach(label      , 0, 0, 1, 1);
        grid.attach(*spinbutton, 1, 0, 1, 1);
    
        add(grid);
    
        show_all();
    }
    
    int main()
    {
        auto application = Gtk::Application::create("test.focus.spinbutton");
    
        SpinButtonExample test;
    
        return application->run(test);
    }
    

    See also https://developer.gnome.org/gtkmm-tutorial/stable/sec-memory-widgets.html.en