如何在gtk + c中回调之间进行通信

我正在研究一个项目,我试图通过向它们传递相同的变量(回调共享相同的变量)使2个回调相互通信。 由于回调函数不能返回值,因此我传递了一个指向主循环(main函数)中赋值的指针。 但是,它根本不起作用!

这是我的代码:

#include  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; } 

该程序在窗口中有3个按钮:

  1. 将值加1
  2. 将10添加到值
  3. 退出计划

value是主循环上的整数。 按下其中一个按钮(第一个或第二个)时,值越大(1或10),程序将打印新值。

我已经运行程序并单击按钮,这就是我所拥有的:

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

代替:

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

谁知道为什么会这样?

谢谢你的帮助!

编辑:我尝试了同样的事情,而不是添加数字值,我试图添加按钮到网格。 由于答案(在问题下)的解决方案在前面的代码中工作,我已经使网格全局化了。

所以这是新代码:

 #include  #include  #include  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; } 

但是,由于某种原因它没有起作用。 帮助将不胜感激!

回复编辑

您必须显示小部件才能实现它们。 最简单的方法是在父容器上调用gtk_widget_show_all

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

另一种选择是保持对按钮的引用并在该实例上调用gtk_widget_show 。 例如:

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

value是本地activateactivate完成后,其局部变量消失; 传递给处理程序的指针现在毫无意义。

解决方案是在应用程序的整个生命周期内使value生存。 最简单(但可能不是最干净)的方法是使其全球化。