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.