How to communicate between callbacks in gtk + c

I'm working on a project right now and I'm trying to make two callbacks with each other by passing the same variable to them (callbacks use the same variable). Since callbacks cannot return a value, I passed in a pointer to the value that is assigned in the main loop (main function). However, it doesn't work 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:

  • adding 1 to value
  • adding 10 to the value
  • exit the program

The value is an integer in the main loop. When one of the buttons (first or second) is pressed, the value becomes larger (by 1 or ten) and the program prints the new value.

I ran the program and clicked buttons and what I have is:

value is: 46525384
value is: 46525384
value is: 46157330
value is: -830528646
value is: 56
value is: 10 

      

instead:

value is: 1
value is: 2
value is: 12
value is: 22
value is: 23
value is: 33

      

Does anyone know why this is happening?

Thanks for the help!

Edit: I tried the same, just instead of adding numbers to the value, I tried to add a button to the grid. Since the solution from the answer (on the question) worked with the previous code, I made the grid global.

So here's 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, for some reason it didn't work. Help would be appreciated!

+1


source to share


2 answers


EDIT answer :

You have to show widgets for them to be implemented. The easiest way is to call gtk_widget_show_all

in 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 is to store the link to the button and call it gtk_widget_show

in that instance. eg:.

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);
}

      

+1


source


value

is local to activate

. When it activate

exits, its local variables disappear; the pointer you pass to the handlers is now meaningless.



The solution is to make the value

application last for life. The simplest (but perhaps not the cleanest) way is to make it global.

+1


source







All Articles