How to communicate between callbacks in gtk+ c

泄露秘密 提交于 2019-12-11 08:26:32

问题


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:

  1. adding 1 to value
  2. adding 10 to value
  3. quitting the program

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!


回答1:


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



回答2:


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.



来源:https://stackoverflow.com/questions/44975598/how-to-communicate-between-callbacks-in-gtk-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!