Search code examples
cgtkgtk3

How to make multiple views in GTK application


I want to make a GTK+ application with multiple views and I don't really know how to achieve it in the best possible way. In every view i need to have some labels and buttons. Firstly I tried to make the appliaction with GtkStack, but StackSwitcher has poor customization options (its buttons are in row and stackswitcher icon's are too small, even with maximum possible size with “icon-size” property).

Connecting stack's page switching with normal buttons would solve the case, but i have no idea how to do such a thing.

My second approach was with multiple windows. I was able to make a few windows and hiding/showing them with buttons. Unfortunately the app will be working on quite bad pc (what's more pc is connected to touchscreen what make it's performance even worse) and after some tests I can say that app has some lags. The whole thing makes all windows in the beggining and then just hide them or show them (depends on what button on which window was pressed).

To sum up my question:

  1. what is the most optimal way to make such an application? With multiple windows or with GtkStack?
  2. If with windows how to optimize the whole thing?
  3. if with stack how to implement switchng stack's tab on normal buttons?

Solution

  • I prefer GtkStack. It has awesome gtk_stack_set_visible_child_name, which let's you set visible child by it's ID. In the following snippet I use GtkListBox for switching (and I had to store a GPtrArray with child names)

    static void
    row_activated (GtkListBox    *box,
                   GtkListBoxRow *row,
                   gpointer       udata)
    {
      MyWid *self = udata;
      MyWidPrivate *priv = self->priv;
    
      gint row_index = gtk_list_box_row_get_index (row);
      gchar *path = g_ptr_array_index (priv->paths, row_index);
    
      gtk_stack_set_visible_child_name (priv->stack, path);
    }
    

    If you want to use GtkButton thing are even more simple:

    gchar *id; // just a string, that allows you to connect buttons and tabs
    GtkWidget *child, *button;
    child = create_tab_for_id (id); // not a real function! You should define it yourself
    gtk_stack_add_named (stack, child, id);
    button = create_button_for_id (id); // also not a real function
    /* Time for magic */
    g_signal_connect_swapped (button, "clicked", 
                              G_CALLBACK (gtk_stack_set_visible_child_name),
                              stack);