Home > front end >  How can I configure a GtkWidget signal that runs every time a widget is shown?
How can I configure a GtkWidget signal that runs every time a widget is shown?

Time:08-05

The show signal seems to only be called the first time a widget is shown. If I call gtk_widget_show on the widget in question, if it has already been shown, any functions passed to g_signal_connect to the widget in question with the show signal will not be called. I attempted to use the show signal for a button whose text is determined by an external state that the button changes, so when the button first becomes visible it successfully shows the initial state, but even though I change the state in the button handler then call gtk_widget_show, the text is not updated when the button is clicked. How can I configure a widget to run on EVERY show event, not just the first.

CodePudding user response:

Requirement:

  • update button label based on state
  • state change happen on button click

One solution could be to update the status when the button is clicked, and then set the button's label, e.g. like this:

update_state();
gtk_button_set_label(button, state);

If more parts of the user interface than just the button should be updated, one could think about introducing a separate function updateUI.

A small demo could look like this:

#include <gtk/gtk.h>

static int cnt;
static char state[16];

static void update_state() {
    snprintf(state, sizeof(state), "clicked %d", cnt  );
}

static void button_show(__unused GtkWidget *widget, __unused gpointer data) {
    g_print("show\n");
}

static void button_clicked(GtkButton *button, __unused gpointer data) {
    g_print("clicked\n");
    update_state();
    gtk_button_set_label(button, state);
}

static void buildUI(GApplication *app, __unused gpointer data) {
    GtkWidget *window = gtk_application_window_new(GTK_APPLICATION(app));
    gtk_window_set_title(GTK_WINDOW(window), "GtkButton");
    gtk_window_set_default_size(GTK_WINDOW(window), 300, 200);
    gtk_container_set_border_width(GTK_CONTAINER(window), 15);
    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);

    GtkWidget *button = gtk_button_new();
    gtk_button_set_label(GTK_BUTTON(button), state);

    gtk_widget_set_size_request(button, 80, 32);

    gtk_widget_set_halign(button, GTK_ALIGN_START);
    gtk_widget_set_valign(button, GTK_ALIGN_START);
    gtk_container_add(GTK_CONTAINER(window), button);

    g_signal_connect(G_OBJECT(button), "clicked",
                     G_CALLBACK(button_clicked), NULL);

    g_signal_connect(G_OBJECT(button), "show",
                     G_CALLBACK(button_show), NULL);

    g_signal_connect(G_OBJECT(window), "destroy",
                     G_CALLBACK(gtk_main_quit), NULL);

    gtk_widget_show_all(GTK_WIDGET(window));
}

int main(int argc, char *argv[]) {
    GtkApplication *app = gtk_application_new("com.example.MyApp", G_APPLICATION_FLAGS_NONE);
    update_state();
    g_signal_connect(app, "activate", G_CALLBACK(buildUI), NULL);
    g_application_run(G_APPLICATION(app), argc, argv);
    g_object_unref(app);
    return 0;
}

It updates the label whenever the button is clicked.

  •  Tags:  
  • c gtk
  • Related