c - GTK2+ error: GTK_IS_CONTAINER & GTK_IS_WIDGET failed -
it's first post here, made account because i'm kind of stumped. i'm trying practise passing structures arguments callbacks, , purpose created simple program button in window. in first iteration, pressing button label "button 1" change different button label "button 2", while in second change done hovering on buttons. below code first iteration
#include <gtk/gtk.h> typedef struct { gtkwidget *button1; gtkwidget *button2; gtkwidget *window; } example; void callback_func (gtkwidget *ignored, example *test) { gtkwidget *window=test->window; gtkwidget *changebutton1=test->button1; gtkwidget *changebutton2=test->button2; gtk_container_remove(gtk_container(window),changebutton1); gtk_container_add(gtk_container(window),changebutton2); gtk_widget_show_all(window); } void callback_func2 (gtkwidget *ignored, example *test) { gtkwidget *window=test->window; gtkwidget *changebutton1=test->button1; gtkwidget *changebutton2=test->button2; gtk_container_remove(gtk_container(window),changebutton2); gtk_container_add(gtk_container(window),changebutton1); gtk_widget_show_all(window); } int main(int argc, char *argv[]) { example test; gtk_init(&argc,&argv); gtkwidget *window=gtk_window_new(gtk_window_toplevel); gtkwidget *changebutton1=gtk_button_new_with_label("button 1"); gtkwidget *changebutton2=gtk_button_new_with_label("button 2"); test.window=window; test.button1=changebutton1; test.button2=changebutton2; g_signal_connect (g_object (window), "delete_event", g_callback (gtk_main_quit), null); g_signal_connect (g_object (window), "destroy", g_callback (gtk_main_quit), null); gtk_container_add(gtk_container(window),changebutton1); g_signal_connect (g_object (changebutton1), "clicked", g_callback (callback_func), (gpointer*)&test); g_signal_connect (g_object (changebutton2),"clicked",g_callback(callback_func2),(gpointer*)&test); gtk_widget_show_all(window); gtk_main (); return 0; } when running above code, clicking button once, buttons switch properly, when click again (now calling callback_func2 instead of callback_func, identical save buttons switching place) this: (gtktesting.exe:92024): gtk-critical **: gtk_container_add: assertion `gtk_is_widget (widget)' failed
if replace "clicked" events "enter_notify_event" , "leave_notify_event", first change fails well, yielding more errors.
anybody know what's going on?
also, bonus question. pretty copied , pasted base of code post, since had been trying write myself unsuccessfully , wanted test if works @ all. noticed second argument in callbacks "example *test". can explain "example" type? it's name of stucture, , i've no idea it's doing there.
tl;dr
try:
test.window = g_object_ref(window); test.button1 = g_object_ref(changebutton1); test.button2 = g_object_ref(changebutton2); full explaination
objects (i.e. subclasses of gobject) in gtk+ reference counted. means, every object (e.g. widget) has "reference count" - number of pointers point it. when number reaches 0 - object deallocated. objects created reference count of 1. c not have smart pointers c++ nor similar, reference counting has done manually. user has call g_object_ref in order retain reference (i use words "pointer" , "reference" interchangeably), , g_object_unref when user done reference. ensures no object destroyed while being in use.
gtkwidget special, begins life "floating" reference. means first time widget referenced reference count not increase - "floating" reference "sunk". after behaves other gobject.
when create buttons, created reference count 1 ("floating"). when added container, references still 1 (but "sunk"). means, buttons owned container they're added to.
now, when remove button container:
gtk_container_remove(gtk_container(window),changebutton1); reference count changebutton1 decreased, drops 0, forces object destruction, , test.button1 dangling pointer.
to overcome this, use g_object_ref anytime want store pointer gobject. way express "test participates in ownership of changebutton1" (or, "test interested in keeping changebutton1 alive).
when done window, button1 , button2, call g_object_unref on them.
bonus question
also, bonus question. pretty copied , pasted base of code post, since had been trying write myself unsuccessfully , wanted test if works @ all. noticed second argument in callbacks "example *test". can explain "example" type? it's name of stucture, , i've no idea it's doing there.
example defined here:
typedef struct { gtkwidget *button1; gtkwidget *button2; gtkwidget *window; } example; // declares type "example" gobject signal system designed in sucha way allows passing arbitrary pointer last argument callback, programmer can pass information place signal connection created (g_signal_connect), callback.
Comments
Post a Comment