Re: gtk_container_remove() and pack later again



On Fri, Jan 22, 2010 at 03:13:58PM +0100, fkater googlemail com wrote:
I have some strange effects: Nearly all displayed text in
widgets (labels, buttons etc) is *sometimes* suddenly
replaced by squares. I suspect the bug is somewhere around
gtk_container_remove().

So, could anyone please confirm if this is correctly coded:



(1) To remove a child for possible later usage I do:

g_object_ref(G_OBJECT(child)); 

gtk_container_remove(
  GTK_CONTAINER(container),GTK_WIDGET(child));

/* it is unclear at coding time if the wiget will ever
 * be needed again or not, so: */
g_object_force_floating(child));



(2) To later re-pack the child

/* I hope this does internally g_object_ref_SINK() ...: */
gtk_box_pack_start/end(
  GTK_BOX(container), child, ...);



(3) Before the child is destroyed (app closed) I do: */

...

if( g_object_is_floating( G_OBJECT(child) ))
{

  g_object_ref_sink( G_OBJECT(child) );

  g_object_unref( G_OBJECT(child) );

}

In any case, it's overengineered.  Containers do not require the widgets
put to them to have floating references; they do g_object_ref_sink()
which either adds a reference or changes the floating reference to
normal one.  So, you can do

0) When you create the child widget:

g_object_ref(child);

1) When you remove the child from its container:

nothing special

2) When you repack the child elsehwere

nothing special

3) When you are definitely done with the child widget:

g_object_unref(child);

See the attached demo.

Yeti

====================================================================
#include <gtk/gtk.h>

static void
swallow(GtkWidget *button,
        GtkWidget *label)
{
    GtkWidget *parent_b, *parent_l;

    parent_b = gtk_widget_get_parent(button);
    parent_l = gtk_widget_get_parent(label);
    if (parent_l == parent_b)
        return;

    gtk_container_remove(GTK_CONTAINER(parent_l), label);
    gtk_box_pack_end(GTK_BOX(parent_b), label, TRUE, TRUE, 12);
}

static void
construct(GtkWidget *label, gboolean pack_here)
{
    GtkWidget *window, *vbox, *button;

    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);

    vbox = gtk_vbox_new(FALSE, 0);
    gtk_container_add(GTK_CONTAINER(window), vbox);

    button = gtk_button_new_with_label("Swallow Label");
    gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0);
    g_signal_connect(button, "clicked", G_CALLBACK(swallow), label);

    if (pack_here)
        gtk_box_pack_end(GTK_BOX(vbox), label, TRUE, TRUE, 12);

    gtk_widget_show_all(window);
}

static void
finalized(G_GNUC_UNUSED gpointer unused,
          G_GNUC_UNUSED GObject *label)
{
    g_print("Label finalized.\n");
}

int
main(int argc, char *argv[])
{
    GtkWidget *label;

    gtk_init(&argc, &argv);
    label = gtk_label_new("Label");
    g_object_ref(label);
    g_object_weak_ref(G_OBJECT(label), finalized, NULL);
    construct(label, TRUE);
    construct(label, FALSE);
    construct(label, FALSE);
    gtk_main();
    g_object_unref(label);

    return 0;
}
====================================================================



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]