How to understand Gtk+ properties and make GtkGrid expand to available area?

8.1k views Asked by At

I'm stumbling through Gtk+ tutorials and the reference, trying to understand how to get a decent layout done. The docs say you should use GtkGrid instead of the deprecated Box/HBox/VBox, but I’m having trouble getting the GtkGrid to expand to the full window size. Using gtk_widget_set_hexpand has no effect on the GtkGrid at all.

This answer suggests "looking at the expand property" but I can't find information about what this properties actually are and how you set them (I just assumed there always is a getter/setter pair for each property, but in this case there is no gtk_widget_set_expand function).

What am I missing?


Update:

Setting the expand property still won't work - the buttons "stick" in the top left corner of the window. Here's the code:

static void initializeGui() {
    GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(window), "Blabla");
    gtk_window_set_default_size(GTK_WINDOW(window), 800, 500);
    gtk_window_set_hide_titlebar_when_maximized(GTK_WINDOW(window), TRUE);
    gtk_container_set_border_width(GTK_CONTAINER(window), 10);
    g_signal_connect(window, "delete-event", G_CALLBACK(onWindowDelete), NULL);
    g_signal_connect(window, "destroy", G_CALLBACK(onWindowDestroy), NULL);

    GtkWidget *mainbox = gtk_grid_new();
    g_object_set(G_OBJECT(mainbox), "expand", TRUE, NULL);
        GtkWidget *button = gtk_button_new_with_label("Short button");
        g_signal_connect(button, "clicked", G_CALLBACK(onButtonClick), NULL);
        gtk_grid_attach(GTK_GRID(mainbox), button, 0, 0, 1, 1);

        button = gtk_button_new_with_label("Very very long button");
        gtk_grid_attach(GTK_GRID(mainbox), button, 1, 0, 1, 1);

        button = gtk_button_new_with_label("Tiny btn");
        gtk_widget_set_halign(button, GTK_ALIGN_END);
        gtk_grid_attach(GTK_GRID(mainbox), button, 1, 1, 1, 1);
    gtk_container_add(GTK_CONTAINER(window), mainbox);   
    gtk_widget_show_all(window);
}
2

There are 2 answers

5
Jussi Kukkonen On BEST ANSWER

It is very hard to say what you are missing since you did not include example code. In addition to hexpand and vexpand, knowing the halign and valign properties could be helpful -- although what you described should be doable with just the expands.

You should also be aware of the older way of dealing with this, container "child properties" (see e.g. gtk_box_pack_start() to see how they were/are used). This can get confusing as there is a expand child property and the hexpand/vexpand widget properties... Both are clearly documented though.

The docs say you should use GtkGrid instead of the deprecated Box/HBox/VBox

This is not the whole story with regards to GtkBox: it is not deprecated and can be used when you need a column or row container. That said, a single row/column GtkGrid does the exact same thing and has, in my opinion, a cleaner api...

I can't find information about what this properties actually are and how you set them

The documentation typically explains what the properties are: https://developer.gnome.org/gtk3/stable/GtkWidget.html#GtkWidget--expand. If there is no setter (or you want to set multiple properties at once) you can use g_object_set:

g_object_set (widget, "expand", TRUE, NULL);

Update:

From the added code it seems like GtkGrid is actually expanded as you want (but that is impossible to visually confirm). The buttons on the other hand are not set to expand. If you do that, I believe you can even remove the GtkGrids expand because the property should "propagate up" the container chain).

You haven't mentioned what you wanted the buttons to do, but you may want to then use halign/valign for different alignments (fill/center/etc).

Update 2:

Based on the description of what you really wanted to achieve, the below changes seem to do what you ask for. The button on the left is set to expand and align to left, the other buttons align to right: as a result all buttons hug the sides of the window and have the minimum width.

#include <gtk/gtk.h>

int main( int argc, char *argv[])
{
    gtk_init(&argc, &argv);

    GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_default_size(GTK_WINDOW(window), 800, 500);

    GtkWidget *mainbox = gtk_grid_new();

    GtkWidget *button = gtk_button_new_with_label("Short button");
    gtk_widget_set_hexpand (button, TRUE);
    gtk_widget_set_halign (button, GTK_ALIGN_START);
    gtk_grid_attach(GTK_GRID(mainbox), button, 0, 0, 1, 1);

    button = gtk_button_new_with_label("Very very long button");
    gtk_widget_set_halign(button, GTK_ALIGN_END);
    gtk_grid_attach(GTK_GRID(mainbox), button, 1, 0, 1, 1);

    button = gtk_button_new_with_label("Tiny btn");
    gtk_widget_set_halign(button, GTK_ALIGN_END);
    gtk_grid_attach(GTK_GRID(mainbox), button, 1, 1, 1, 1);

    gtk_container_add(GTK_CONTAINER(window), mainbox);
    gtk_widget_show_all(window);

    gtk_main();

    return 0;
}
0
Andy Tao On

follow code is Vala code to show grid and expand property:

            m_form_detail_grid = new Gtk.Grid();
            m_form_detail_grid.row_spacing = 10;
            m_form_detail_grid.column_spacing = 5;
            // m_form_detail_grid.column_homogeneous = true;
            m_form_detail_grid.expand = true;
            m_form_detail_grid.margin = 30;
            m_form_detail_grid.orientation = Gtk.Orientation.VERTICAL;


            for (int index = 0; index < column_count; index++) {
                column_title = this.m_data_model.get_column_title(index).replace ("_", "__"); 
                column_label = new Gtk.Label(column_title);
                column_label.hexpand = false;
                column_label.halign = Gtk.Align.END;

                column_widget = new Gtk.Entry();
                column_widget.editable = true;
                column_widget.hexpand = true;
                column_widget.halign = Gtk.Align.FILL;

                m_form_detail_grid.attach (column_label, 0, index, 1, 1);
                m_form_detail_grid.attach (column_widget, 1, index, 7, 1);
            }