Reputation: 263
I'm working on a project right now, and I am trying to make 2 callbacks communicate with each other by passing to them the same variable (the callbacks share the same variable). Since the callbacks cannot return a value, I have passed a pointer to the value which is assigned in the main loop (main function). However, it isn't working at all!
This is my code:
#include <gtk/gtk.h>
static void inc_val (GtkWidget *widget, gpointer data)
{
int* value = data;
*value++;
printf("value is: %d\n", *value);
}
static void inc_val_ten (GtkWidget *widget, gpointer data)
{
int* value = data;
*value+=10;
printf("value is: %d\n", *value);
}
static void activate (GtkApplication *app, gpointer user_data)
{
GtkWidget *window;
GtkWidget *grid;
GtkWidget *button;
int value = 0;
window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "Window");
gtk_container_set_border_width (GTK_CONTAINER (window), 10);
grid = gtk_grid_new ();
gtk_container_add (GTK_CONTAINER (window), grid);
button = gtk_button_new_with_label ("Add 1 to value");
g_signal_connect (button, "clicked", G_CALLBACK (inc_val), &value);
gtk_grid_attach (GTK_GRID (grid), button, 0, 0, 1, 1);
button = gtk_button_new_with_label ("Add 10 to value");
g_signal_connect (button, "clicked", G_CALLBACK (inc_val_ten), &value);
gtk_grid_attach (GTK_GRID (grid), button, 1, 0, 1, 1);
button = gtk_button_new_with_label ("Quit");
g_signal_connect_swapped (button, "clicked", G_CALLBACK (gtk_widget_destroy), window);
gtk_grid_attach (GTK_GRID (grid), button, 0, 1, 2, 1);
gtk_widget_show_all (window);
}
int main (int argc, char **argv)
{
GtkApplication *app;
int status;
app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE);
g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
status = g_application_run (G_APPLICATION (app), argc, argv);
g_object_unref (app);
return status;
}
The program has 3 buttons in the window:
value is an integer on the main loop. When one of the buttons (first or second) are pressed, the value getting bigger (by 1 or by ten) and the program prints the new value.
I have run the program and clicked the buttons and that's what I've got:
value is: 46525384
value is: 46525384
value is: 46157330
value is: -830528646
value is: 56
value is: 10
instead of:
value is: 1
value is: 2
value is: 12
value is: 22
value is: 23
value is: 33
Anyone knows why does it happen?
Thanks for helping!
Edit: I have tried the same thing, just instead of adding numbers to a value, I've tried to add button to the grid. Since the solution from the answer (under the question) worked at the previous code, I've made the grid global.
So here is the new code:
#include <gtk/gtk.h>
#include <stdlib.h>
#include <stdio.h>
GtkWidget *grid;
static void add_button (GtkWidget *widget, gpointer data)
{
static int value = 0;
GtkWidget* grid = data;
value++;
printf("attach to line %d\n", value);
gtk_grid_attach(GTK_GRID(grid), gtk_button_new_from_stock(GTK_STOCK_NEW), 0, value, 1, 1);
}
static void activate (GtkApplication *app, gpointer user_data)
{
GtkWidget *window;
GtkWidget *button;
window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "Window");
gtk_container_set_border_width (GTK_CONTAINER (window), 10);
grid = gtk_grid_new ();
gtk_container_add (GTK_CONTAINER (window), grid);
button = gtk_button_new_with_label ("Add Button");
g_signal_connect (button, "clicked", G_CALLBACK (add_button), grid);
gtk_grid_attach (GTK_GRID (grid), button, 0, 0, 1, 1);
gtk_widget_show_all (window);
}
int main (int argc, char **argv)
{
GtkApplication *app;
int status;
app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE);
g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
status = g_application_run (G_APPLICATION (app), argc, argv);
g_object_unref (app);
return status;
}
However, it didn't work from some reason. Help will be appreciated!
Upvotes: 1
Views: 560
Reputation: 4114
Answer to the EDIT:
You must show the widgets in order for them to be realized. Simplest way is to call gtk_widget_show_all
on the parent container:
static void add_button (GtkWidget *widget, gpointer data)
{
static int value = 0;
GtkWidget* grid = data;
value++;
printf("attach to line %d\n", value);
gtk_grid_attach(GTK_GRID(grid),
gtk_button_new_from_stock(GTK_STOCK_NEW), 0, value, 1, 1);
gtk_widget_show_all(grid);
}
Another option, would be to keep a reference to the button and call gtk_widget_show
on that instance. e.g.:
static void add_button (GtkWidget *widget, gpointer data)
{
static int value = 0;
GtkWidget* grid = data;
GtkWidget* button = gtk_button_new_from_stock(GTK_STOCK_NEW);
value++;
printf("attach to line %d\n", value);
gtk_grid_attach(GTK_GRID(grid), button, 0, value, 1, 1);
gtk_widget_show (button);
}
Upvotes: 1
Reputation: 7923
The value
is local to activate
. When activate
completes, its local variables are gone; the pointer you pass to the handlers is now meaningless.
The solution is to make value
surviving an entire lifetime of the application. A simplest (but possibly not cleanest) way is to make it global.
Upvotes: 1