1
votes

I'm new to GTK+ programming,i'm on it since one week and I mainly met only one big problem,here the code to explain:

for(j=1;j<5;j++)
{
for(i=1;i<6;i++)
{
    box[i][j] = gtk_hbox_new(TRUE, 0);
    check[i][j]=gtk_check_button_new();
    event[i][j]= gtk_event_box_new ();
    gtk_container_add (GTK_CONTAINER (event[i][j]),color[i][j]);
    gtk_box_pack_start(box[i][j],check[i][j], TRUE, FALSE, 0);
    gtk_box_pack_start(box[i][j],event[i][j], TRUE, FALSE, 0);
    gtk_widget_set_events (event[i][j], GDK_BUTTON_PRESS_MASK);
    gtk_table_attach_defaults(table,box[i][j],j-1, j, i, i+1);
}
}

I have a table,and for each (i,j) I have a box that contains a clickable image and a checkbox,I want to turn the check[i][j] checked/not checked when I click on event[i][j] (the clickable image) So the signal would be like this

g_signal_connect (GTK_OBJECT(event[i][j]), "button-press-event",G_CALLBACK(events),NULL);

and the callback function would be like this

void events(void)
{
void* k;
k= gtk_toggle_button_get_active(check[i][j]);
if(k==FALSE)
{
    gtk_toggle_button_set_active(check[i][j],TRUE);
}
else
{
    gtk_toggle_button_set_active(check[i][j],FALSE);
}
}

I didn't find how to pass i and j to the callback,I have changed NULL in the g_signal_connect with a struct/tab that contains i and j,(also added gpointer data and all requiered things in the callback)but didn't work... I have spent a lot of time seaching on the internet but I didn't find what I really need. The only solution I found so far is to create 20 callback functions and 20 g_signal_connect for each i,j,but it took about 270 lines to code... Your help would be really appreciated :D

To explain more : This is th struct :

typedef struct {
int i;
int j;
} t_ig ;
t_ig a;

The loop :

for(j=1;j<5;j++)
{
for(i=1;i<6;i++)
{
    box[i][j] = gtk_hbox_new(TRUE, 0);
    check[i][j]=gtk_check_button_new();
    event[i][j]= gtk_event_box_new ();
    gtk_container_add (GTK_CONTAINER (event[i][j]),color[i][j]);
    tr=event[i][j];
    gtk_box_pack_start(box[i][j],check[i][j], TRUE, FALSE, 0);
    gtk_box_pack_start(box[i][j],event[i][j], TRUE, FALSE, 0);
    gtk_widget_set_events (event[i][j], GDK_BUTTON_PRESS_MASK);
    a.i=i;
    a.j=j;
    g_signal_connect (GTK_OBJECT(tr)), "button-press-event",G_CALLBACK(events),&a);
}

The callback

void events(GtkWidget * tr, gpointer userdata)
{
t_ig * d = (t_ig *) userdata ;
printf ("%d",d->i);
}

I should normally get the i that I have initialized with a.i=i; and since i'm not getting the requiered values of i and j I can't edit check[i][j]

EDIT : My problem is solved,for those who might be interested here is the code:

     for(j=1;j<5;j++)
{
for(i=1;i<6;i++)
{
    box[i][j] = gtk_hbox_new(TRUE, 0);
    check[i][j]=gtk_check_button_new();
    event[i][j]= gtk_event_box_new ();
    gtk_container_add (GTK_CONTAINER (event[i][j]),color[i][j]);
    tr=event[i][j];
    gtk_box_pack_start(box[i][j],check[i][j], TRUE, FALSE, 0);
    gtk_box_pack_start(box[i][j],event[i][j], TRUE, FALSE, 0);
    gtk_widget_set_events (event[i][j], GDK_BUTTON_PRESS_MASK);
    g_signal_connect ((GTK_OBJECT(event[i][j])), "button-press-event",G_CALLBACK(events),check[i][j]);
}
}

The callback :

void events(GtkWidget * wid,GdkEvent  *event, gpointer userdata)
{

GtkWidget * d=userdata;
void* k;
k= gtk_toggle_button_get_active(d);
if(k==FALSE)
{
    gtk_toggle_button_set_active(d,TRUE);
}
else
{
    gtk_toggle_button_set_active(d,FALSE);
}
(void) wid;
}

And thank you all for your answers :D

1
Normally, you have to create a struct that will contain the data you need to pass to the callback, and pass this struct as the last argument. Can you give us more details about how you tried this, maybe we can find out why it didn't workMansuro
try casting &a in g_signal_connect to (gpointer)Mansuro
Alrealy did,but I still have random values when I try the printf to see if "i" had been initialized or not :/Clyde

1 Answers

0
votes

button-press-event is defined like this:

gboolean
user_function (GtkWidget *widget,
               GdkEvent  *event,
               gpointer   user_data)

Your callback must have this signature.

The second problem is that you are reusing the same data struct. That won't work: you need to allocate a struct for each different one: e.g. ti_g *data = g_slice_new0 (ti_g);

However... if you just want to modify a specific checkbox from the callback, why don't you just give a pointer to that checkbox as a userdata pointer, like so:

gboolean
button_press_event_cb (GtkWidget *widget,
                       GdkEvent  *event,
                       gpointer   user_data)
{
    GtkToggleButton *btn = GTK_TOGGLE_BUTTON (user_data);
    gboolean active = gtk_toggle_button_get_active (btn);

    gtk_toggle_button_set_active (btn, !active);

    return TRUE;
}

/* ... in construction code ... */    
g_signal_connect (event[i][j], "button-press-event",
                  G_CALLBACK(button_press_event_cb), check[i][j]);