使用GtkBuilder要注意的问题

 

最近想用GTK实现一个系统托盘,我使用的开发工具是Anjuta+Glade,很自然就会用到GtkBuilder。结果问题来了,弹出式菜单显示不了, 出现了如下的错误:

 

(monitor:3810): Gtk-CRITICAL **: gtk_status_icon_set_visible: assertion `GTK_IS_STATUS_ICON (status_icon)' failed


(monitor:3810): Gtk-CRITICAL **: gtk_menu_popup: assertion `GTK_IS_MENU (menu)' failed

看来,不仅仅弹出式菜单有问题,status icon也是有问题的。
我的代码很简单,会有什么问题呢?

 

GtkStatusIcon* create_tray(gpointer user_data) { GtkStatusIcon *status_icon; GtkBuilder *status_icon_builder; GError *error = NULL; status_icon_builder = gtk_builder_new(); if(!gtk_builder_add_from_file (status_icon_builder,WINDOW_UI_FILE,&error)) { g_warning ("Couldn't load status_icon_builder file: %s", error->message); g_error_free (error); } gtk_builder_connect_signals (status_icon_builder,user_data); status_icon = GTK_STATUS_ICON(gtk_builder_get_object (status_icon_builder, "status_icon")); g_object_unref(status_icon_builder); return status_icon; } GtkMenu *create_popup_menu() { GtkMenu *menu; GtkBuilder *menu_builder; GError *error = NULL; menu_builder = gtk_builder_new (); if(!gtk_builder_add_from_file (menu_builder,WINDOW_UI_FILE,&error)) { g_warning ("Couldn't load menu_builder file: %s", error->message); g_error_free (error); } gtk_builder_connect_signals (menu_builder,NULL); menu = GTK_MENU(gtk_builder_get_object(menu_builder,"popup_menu")); g_object_unref (menu_builder); return menu; }  
查过了资料才发现,原来是GtkBuilder所引起的。

A GtkBuilder holds a reference to all objects that it has constructed and drops these references when it is finalized. This finalization can cause the destruction of non-widget objects or widgets which are not contained in a toplevel window. For toplevel windows constructed by a builder, it is the responsibility of the user to call gtk_widget_destroy() to get rid of them and all the widgets they contain.

The functions gtk_builder_get_object() and gtk_builder_get_objects() can be used to access the widgets in the interface by the names assigned to them inside the UI description. Toplevel windows returned by these functions will stay around until the user explicitly destroys them with gtk_widget_destroy(). Other widgets will either be part of a larger hierarchy constructed by the builder (in which case you should not have to worry about their lifecycle), or without a parent, in which case they have to be added to some container to make use of them. Non-widget objects need to be reffed with g_object_ref() to keep them beyond the lifespan of the builder.


原来GtkStatusIcon和GtkMenu一个是non-widget,一个是widget,但不是toplevel,一旦GtkBuilder的对象被回收,它们也会被释放.所以在使用完GtkBuilder后,我们不能让系统将它回收,不然,GtkStatusIcon和GtkMenu的对象也会被释放的。因此,将g_object_unref改成g_object_ref,让GtkBuilder的reference count不为0,等到释放GtkStatusIcon和GtkMenu对象后,系统就会回收GtkBuilder对象的。在这里,也不能不加g_object_ref,不然,就很容易造成内存泄漏。

 

你可能感兴趣的:(object,File,reference,hierarchy,menu,gtk)