[GTK]将g_signal_connect中的循环计数器传递给g_callback

时间:2014-07-10 11:36:02

标签: c loops variables callback gtk

我是GTK +编程的新手,我在一周之后开始研究它,我主要只遇到一个大问题,这里是代码解释:

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,j)我有一个包含可点击图像和复选框的框,我想在点击事件时关闭检查[i] [j]检查/不检查[i] [j](可点击图片) 所以信号就像这样

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

并且回调函数就像这样

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和j传递给回调,我在g_signal_connect中使用包含i和j的结构/选项卡更改了NULL(还添加了gpointer数据和回调中的所有必需内容) )但没有工作...... 我花了很多时间在互联网上搜索,但我没有找到我真正需要的东西。 到目前为止我找到的唯一解决方案是为每个i,j创建20个回调函数和20个g_signal_connect,但代码需要大约270行... 非常感谢您的帮助:D

要解释更多: 这是结构:

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

循环:

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);
}

回调

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

我通常应该得到我用a.i = i初始化的i;因为我没有得到i和j的必要值,所以我无法编辑check [i] [j]

编辑: 我的问题解决了,对于那些可能感兴趣的人是代码:

     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]);
}
}

回调:

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;
}

谢谢大家的回答:D

1 个答案:

答案 0 :(得分:0)

button-press-event的定义如下:

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

您的回调必须有此签名。

第二个问题是您正在重用相同的数据结构。这不会起作用:你需要为每个不同的分配一个结构:例如ti_g *data = g_slice_new0 (ti_g);

但是......如果您只想修改回调中的特定复选框,为什么不直接将指向该复选框的指针作为用户数据指针,如下所示:

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]);