C和GTK g_signal_connect传递参数

时间:2017-04-06 04:28:28

标签: c gtk3

无法让g_signal_connect正确传递参数。这可能是因为我不理解“c_handler”或“data”参数。代码在这里:

#include <gtk/gtk.h>

// Function prototypes
void my_file_saveas();

// Function
void my_file_saveas(GtkTextBuffer *buf)
{
  // Get the start and end bounds of the buffer
  GtkTextIter start, end;
  gtk_text_buffer_get_bounds (buf, &start, &end);
}

int main(int argc, char *argv[])
{
  GtkWidget *menubar;
  GtkWidget *fileMenu;
  GtkWidget *fileMh;
  GtkWidget *saveasMi;

  GtkWidget *view;
  GtkTextBuffer *buffer;
  GtkWidget *scroll_window;
  GtkWidget *vbox;

  GtkWidget *window;

  // Call this function first
  gtk_init(&argc, &argv);

  // Create widgets
  menubar = gtk_menu_bar_new();
  fileMenu = gtk_menu_new();
  fileMh = gtk_menu_item_new_with_label("File");
  saveasMi = gtk_menu_item_new_with_label("Save As");

  view = gtk_text_view_new();
  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));

  // Set out the menubar
  gtk_menu_shell_append(GTK_MENU_SHELL(fileMenu), saveasMi);
  gtk_menu_item_set_submenu(GTK_MENU_ITEM(fileMh), fileMenu);
  gtk_menu_shell_append(GTK_MENU_SHELL(menubar), fileMh);

  // Create a scroll window and add the view to it
  scroll_window = gtk_scrolled_window_new (NULL, NULL);
  gtk_container_add(GTK_CONTAINER(scroll_window), view);

  // Create a vertical box and add the menubar and scroll_window
  vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
  gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 0);
  gtk_box_pack_start(GTK_BOX(vbox), scroll_window, TRUE, TRUE, 0);

  // Setup top level window
  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
  gtk_window_set_default_size(GTK_WINDOW(window), 640, 480);

  // Put the box in the top level window
  gtk_container_add(GTK_CONTAINER(window), vbox);

  // Events
  g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
  g_signal_connect(G_OBJECT(saveasMi), "activate", G_CALLBACK(my_file_saveas), buffer);

  // Display the window
  gtk_widget_show_all(window);

  // Runs main
  gtk_main();

  return 0;
}

编译好。但是当我运行它时的输出是:

graeme@graeme-HP-xw4300-Workstation ~/c/test $ ./ed10

(ed10:2974): Gtk-CRITICAL **: gtk_text_buffer_get_bounds: assertion 'GTK_IS_TEXT_BUFFER (buffer)' failed

1 个答案:

答案 0 :(得分:0)

您的错误不言自明(有点):

GTK_TEXT_BUFFER

查看您的代码 - 您没有声明独立GtkTextBuffer *)(例如gtk_text_view_newgtk_text_view_new_with_buffer (buffer)将提供默认缓冲区,但您也可以使用gtk_text_buffer_new (NULL);你独立声明一个缓冲区,例如gtk_text_view_new(你会得到一个带有gtk_text_view_new_with_buffer (NULL);menuitem的默认缓冲区。你的选择......,你有什么工作。

您真正的问题是回调函数原型错误,它应该包含您的buffer(这是真正的问题,它会将您的GtkMenuItem作为{{{ 1}}导致错误'GTK_IS_TEXT_BUFFER (buffer)' failed),例如

void my_file_saveas (GtkMenuItem *menuitem, gpointer data)
{
  // Get the start and end bounds of the buffer
  GtkTextBuffer *buf = GTK_TEXT_BUFFER (data);
  GtkTextIter start, end;
  gtk_text_buffer_get_bounds (buf, &start, &end);

  /* print the number of lines to stdout */
  g_print ("Buffer has %d lines.\n", gtk_text_iter_get_line (&end) -
            gtk_text_iter_get_line (&start) + 1);

  if (menuitem) {}  /* stub to suppress warning of unused menuitem */
}

坦率地说,我无法相信它会让你在没有错误(或警告)的情况下进行编译,但确实如此,我编译了:

gcc -Wall -Wextra -pedantic -finline-functions -std=gnu11 ...

它让我用不正确的原型编译 - 把我缠绕在轴上:)

以下是您的代码的工作示例:

#include <gtk/gtk.h>

// Function
void my_file_saveas (GtkMenuItem *menuitem, gpointer data)
{
  // Get the start and end bounds of the buffer
  GtkTextBuffer *buf = GTK_TEXT_BUFFER (data);
  GtkTextIter start, end;
  gtk_text_buffer_get_bounds (buf, &start, &end);
  g_print ("Buffer has %d lines.\n", gtk_text_iter_get_line (&end) -
            gtk_text_iter_get_line (&start) + 1);

  if (menuitem) {}  /* stub to suppress warning of unused menuitem */
}

int main(int argc, char *argv[])
{
  GtkWidget *menubar;
  GtkWidget *fileMenu;
  GtkWidget *fileMh;
  GtkWidget *saveasMi;

  GtkWidget *view;
  GtkTextBuffer *buffer = NULL;
  GtkWidget *scroll_window;
  GtkWidget *vbox;

  GtkWidget *window;

  // Call this function first
  gtk_init(&argc, &argv);

  // Create widgets
  menubar = gtk_menu_bar_new();
  fileMenu = gtk_menu_new();
  fileMh = gtk_menu_item_new_with_label("File");
  saveasMi = gtk_menu_item_new_with_label("Save As");

  /** example declaring independent buffer 
   *
   *  buffer = gtk_text_buffer_new (NULL);
   *  view = gtk_text_view_new_with_buffer(buffer);
   */
  view = gtk_text_view_new();
  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
  if (!view || !buffer) {
    g_print ("error - no view or buf.\n");
    return 1;
  }

  // Set out the menubar
  gtk_menu_shell_append(GTK_MENU_SHELL(fileMenu), saveasMi);
  gtk_menu_item_set_submenu(GTK_MENU_ITEM(fileMh), fileMenu);
  gtk_menu_shell_append(GTK_MENU_SHELL(menubar), fileMh);

  // Create a scroll window and add the view to it
  scroll_window = gtk_scrolled_window_new (NULL, NULL);
  gtk_container_add(GTK_CONTAINER(scroll_window), view);

  // Create a vertical box and add the menubar and scroll_window
  vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
  gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 0);
  gtk_box_pack_start(GTK_BOX(vbox), scroll_window, TRUE, TRUE, 0);

  // Setup top level window
  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
  gtk_window_set_default_size(GTK_WINDOW(window), 640, 480);

  // Put the box in the top level window
  gtk_container_add(GTK_CONTAINER(window), vbox);

  // Events
  g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
  g_signal_connect(G_OBJECT(saveasMi), "activate", G_CALLBACK(my_file_saveas), 
                    buffer);

  // Display the window
  gtk_widget_show_all(window);

  // Runs main
  gtk_main();

  return 0;
}

如果你想看一些更大的例子(GTK + 2,但这里适用100%),请看https://github.com/drankinatty/gtkwrite。 (textview和buffer声明在gtk_windef.c