GTK+ Forums

Discussion forum for GTK+ and Programming. Ask questions, troubleshoot problems, view and post example code, or express your opinions.
It is currently Sat Nov 29, 2014 8:34 am

All times are UTC




Post new topic Reply to topic  [ 7 posts ] 
Author Message
 Post subject: Can a GtkWidget be contained by 2 containers?
PostPosted: Mon Jan 09, 2012 4:27 pm 
Offline
Familiar Face

Joined: Mon Oct 17, 2011 10:18 am
Posts: 26
Hello All,

I will be more than grateful if you could find time for answering me.
I have a complex structure of a GtkWidget that shows a real time video.

Hierarchy:
Container (Gtk Widget) ---points to---> GtkTable (4x4) ---each of cells points to---> EventBox (GtkWidget)
---points to--->GtkWidget ---points to---> GtkPixbuf ---points to---> IplImage (for each frame of the video).

Goal:
I want to implement the next algorithm:
1. Mouse click on one of the images.
2. Hiding all the structure of the 4X4 grid.
3. Showing the clicked image on the area of the 4x4 grid.
* And all the way back as well.

Problem:
Since the inner structure of each cell is complex, I would like to do the next:
1. Attach the existing structure to a new container.
2. Hide the existing 4x4 grid.
3. Show the new created image.

Question:
1. Is it possible?
2. CanĀ“t it cause memory freeing problems? (One container frees the widget, and then there will be a segmentation fault when the other one will try to do the same).

Thank you all for your time,
Felix.


Top
 Profile  
 
 Post subject: Re: Can a GtkWidget be contained by 2 containers?
PostPosted: Tue Jan 10, 2012 9:24 pm 
Offline
Never Seen the Sunlight

Joined: Thu Mar 24, 2011 2:10 pm
Posts: 328
Location: Sydney, Australia
The answer is yes. For example I often have GtkAdjustments bound to multiple spin buttons so that adjusting one will adjust the other automatically.
However your program doesn't seem to necessitate the use of having it in two containers at the same time. There can be memory problems. Gtk uses reference counting to decide when to destroy a widget. Each time a widget is instantiated (e.g. when I add a spin button and assign a common GtkAdjustment) the reference count goes up by 1 and goes down when it is destroyed. When it reduces to zero it is removed from memory. Now if you destroy the table then all contents will be destroyed. You can avoid having the cell contents removed from memory by using g_object_ref and then g_object_unref once you've restored the table again.
Another way is to design a custom widget for your table using cairo and GtkDrawingArea, then you can design in just the signals you need as well as your own funky dynamic behaviour.


Top
 Profile  
 
 Post subject: Re: Can a GtkWidget be contained by 2 containers?
PostPosted: Fri Jan 13, 2012 10:24 am 
Offline
Never Seen the Sunlight

Joined: Wed Jul 23, 2008 10:31 am
Posts: 2406
Location: Slovenia
Hello.

First, answer to the guestion in the title of the topic (Can a GtkWidget be contained by 2 containers?) is no. Widget can be only child of one parent.

As for GtkAdjustment, it can be referenced from several widgets because a) it's not a widget (it is derived from GtkObject and in GTK+-3 it is directly derived from GObject) and b) there is no parent-child relationship with widget-adjustment.

For more info about this specific problem, see topic viewtopic.php?f=3&t=55681

Cheers,
Tadej


Top
 Profile  
 
 Post subject: Re: Can a GtkWidget be contained by 2 containers?
PostPosted: Fri Jan 13, 2012 12:40 pm 
Offline
Familiar Face

Joined: Mon Oct 17, 2011 10:18 am
Posts: 26
Paul Childs wrote:
The answer is yes. For example I often have GtkAdjustments bound to multiple spin buttons so that adjusting one will adjust the other automatically.
However your program doesn't seem to necessitate the use of having it in two containers at the same time. There can be memory problems. Gtk uses reference counting to decide when to destroy a widget. Each time a widget is instantiated (e.g. when I add a spin button and assign a common GtkAdjustment) the reference count goes up by 1 and goes down when it is destroyed. When it reduces to zero it is removed from memory. Now if you destroy the table then all contents will be destroyed. You can avoid having the cell contents removed from memory by using g_object_ref and then g_object_unref once you've restored the table again.
Another way is to design a custom widget for your table using cairo and GtkDrawingArea, then you can design in just the signals you need as well as your own funky dynamic behaviour.


Dear Paul,

First I wanted to thank you for your answer.
The second thing is that it is not very clear to me.
Of course you have given me 3 different directions, and this is already a lot :), but if you have time to explain it more clearly, I would be grateful.

Thanks,
Felix.


Top
 Profile  
 
 Post subject: Re: Can a GtkWidget be contained by 2 containers?
PostPosted: Fri Jan 13, 2012 9:03 pm 
Offline
Never Seen the Sunlight

Joined: Thu Mar 24, 2011 2:10 pm
Posts: 328
Location: Sydney, Australia
Thanks for the correction tadeboro,
as to more information (I thought there was only two):
1. Using the table: Ok ou want to destroy the cell structure of the table in order to focus on just one cell, but doing so will dereference and thus remove from memory all your images. So first call g_object_ref on each of your images and then do the gtk_widget_destroy on the table contents (the images remain in memory and can thus be addressed without seg faults)


2. Custom widget: far to involved for me to even begin to start describing here. There's a tutorial on the gtk website that discusses how to create customised widgets. In this case you would set up a drawing area (where you draw NxM images for the frame preview case and just the 1 for the focused case -- they are not widgets in this case so you don't have to worry about memory concerns) and signals for detecting mouse clicks (which well then detect which cell the click occured in and change to focus). The advantage to customisation is that you can add dynamic behaviour like have a zoom transition in the change as well as having the NxM images scroll rather than replace. Having cairo doing the drawing makes applying image editing very easy. Customisation is a fair bit of work; your main aim I'd imagine woud be to get it up and running at the moment; but if you're going to be continually improving this for a while and adding new features, eventually you're going to run into some problem that needs customisation.


Top
 Profile  
 
 Post subject: Re: Can a GtkWidget be contained by 2 containers?
PostPosted: Fri Jan 13, 2012 10:40 pm 
Offline
GTK+ Geek

Joined: Fri Sep 04, 2009 6:53 am
Posts: 68
There is no GtkPixbuf. There is only a GdkPixbuf which can be can shown in more than one GtkImage at the same time.

For your layout you can use a GtkNotebook without showing the tabs. Something like this (with buttons instead of eventboxes, and labels instead of images for simplicity, gtk+2.0):

Code:
#include <gtk/gtk.h>

GtkWidget *notebook;
GtkWidget *main_label;

void on_button(GtkButton *button, gpointer data)
{
    if (data)
    {
        gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook),1);
        gint ij=GPOINTER_TO_INT(data)-1;
        char buffer[20];
        snprintf(buffer,G_N_ELEMENTS(buffer),"%d,%d",ij%2,ij/2);
        gtk_label_set_text(GTK_LABEL(main_label),buffer);
    }
    else
    {
        gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook),0);
    }
}

int main(int argc, char **argv)
{
    gtk_init(&argc,&argv);
    GtkWidget *window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
    g_signal_connect(G_OBJECT(window),"destroy",G_CALLBACK(gtk_main_quit),NULL);

    notebook=gtk_notebook_new();
    gtk_container_add(GTK_CONTAINER(window),notebook);
    gtk_notebook_set_show_tabs(GTK_NOTEBOOK(notebook),FALSE);

    GtkWidget *table=gtk_table_new(2,2,TRUE);
    gtk_notebook_append_page(GTK_NOTEBOOK(notebook),table,NULL);
    int i;
    for (i=0; i<2; i++)
    {
        int j;
        for (j=0; j<2; j++)
        {
            GtkWidget *button=gtk_button_new();
            gtk_table_attach_defaults(GTK_TABLE(table),button,i,i+1,j,j+1);
            char buffer[20];
            snprintf(buffer,G_N_ELEMENTS(buffer),"%d,%d",i,j);
            gtk_container_add(GTK_CONTAINER(button),gtk_label_new(buffer));
            g_signal_connect(G_OBJECT(button),"clicked",
                             G_CALLBACK(on_button),GINT_TO_POINTER(2*i+j+1));
        }
    }

    GtkWidget *button=gtk_button_new();
    gtk_notebook_append_page(GTK_NOTEBOOK(notebook),button,NULL);

    main_label=gtk_label_new(NULL);
    gtk_container_add(GTK_CONTAINER(button),main_label);
    g_signal_connect(G_OBJECT(button),"clicked",G_CALLBACK(on_button),NULL);

   
    gtk_widget_show_all(window);
    gtk_main();
    return 0;
}


Top
 Profile  
 
 Post subject: Re: Can a GtkWidget be contained by 2 containers?
PostPosted: Fri Jan 13, 2012 11:04 pm 
Offline
GTK+ Geek

Joined: Fri Sep 04, 2009 6:53 am
Posts: 68
And the same with GtkImages instead of GtkLabels but without error handling (images in 0.png, ..., 3.png):

Code:
#include <gtk/gtk.h>

GtkWidget *notebook;
GtkWidget *main_image;
GdkPixbuf *pixbuf[4];

void on_button(GtkButton *button, gpointer data)
{
    if (data)
    {
        gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook),1);
        gtk_image_set_from_pixbuf(
            GTK_IMAGE(main_image),pixbuf[GPOINTER_TO_INT(data)-1]);
    }
    else
    {
        gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook),0);
    }
}

int main(int argc, char **argv)
{
    gtk_init(&argc,&argv);
    GtkWidget *window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
    g_signal_connect(G_OBJECT(window),"destroy",G_CALLBACK(gtk_main_quit),NULL);

    notebook=gtk_notebook_new();
    gtk_container_add(GTK_CONTAINER(window),notebook);
    gtk_notebook_set_show_tabs(GTK_NOTEBOOK(notebook),FALSE);

    GtkWidget *table=gtk_table_new(2,2,TRUE);
    gtk_notebook_append_page(GTK_NOTEBOOK(notebook),table,NULL);

    int i;
    for (i=0; i<2; i++)
    {
        int j;
        for (j=0; j<2; j++)
        {
            GtkWidget *button=gtk_button_new();
            gtk_table_attach_defaults(GTK_TABLE(table),button,i,i+1,j,j+1);
            g_signal_connect(G_OBJECT(button),"clicked",
                             G_CALLBACK(on_button),GINT_TO_POINTER(2*i+j+1));

            char buffer[20];
            snprintf(buffer,G_N_ELEMENTS(buffer),"%d.png",2*i+j);
            pixbuf[2*i+j]=gdk_pixbuf_new_from_file(buffer,NULL);

            GtkWidget *image=gtk_image_new_from_pixbuf(pixbuf[2*i+j]);
            gtk_container_add(GTK_CONTAINER(button),image);
        }
    }

    GtkWidget *button=gtk_button_new();
    gtk_notebook_append_page(GTK_NOTEBOOK(notebook),button,NULL);
    g_signal_connect(G_OBJECT(button),"clicked",G_CALLBACK(on_button),NULL);

    main_image=gtk_image_new();
    gtk_container_add(GTK_CONTAINER(button),main_image);
   
    gtk_widget_show_all(window);
    gtk_main();
    return 0;
}


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 7 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 4 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group