2017-04-06 109 views
0

無法使g_signal_connect正確傳遞參數。它可能是因爲我不明白「c_handler」或「data」參數。代碼在這裏:C和GTK g_signal_connect傳遞參數

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

它編譯好。但是,當我運行它的輸出是在這裏:

[email protected] ~/c/test $ ./ed10 

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

回答

0

你的錯誤是不言自明的(種):

(debugsig:26923): Gtk-CRITICAL **: gtk_text_buffer_get_bounds: 
assertion 'GTK_IS_TEXT_BUFFER (buffer)' failed 

看你的代碼 - 不聲明一個獨立的GTK_TEXT_BUFFER(如GtkTextBuffer *)gtk_text_view_new將提供默認緩衝區,但如果您獨立聲明緩衝區,則可以使用gtk_text_view_new_with_buffer (buffer),例如gtk_text_buffer_new (NULL);(您將得到一個具有gtk_text_view_newgtk_text_view_new_with_buffer (NULL);的默認緩衝區)。您的選擇...,您將擁有的功能。

你真正的問題是你的回調函數原型是錯誤的,它應該包含您的menuitem(那纔是真正的問題,它正在你bufferGtkMenuItem導致錯誤'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和緩衝區聲明在gtk_windef.c