GTK+ Forums

Discussion forum for GTK+ and Programming. Ask questions, troubleshoot problems, view and post example code, or express your opinions.
It is currently Thu Apr 24, 2014 5:21 pm

All times are UTC




Post new topic Reply to topic  [ 8 posts ] 
Author Message
 Post subject: Passing parameters in the callback function
PostPosted: Thu Nov 01, 2012 5:54 pm 
Offline

Joined: Thu Nov 01, 2012 4:41 pm
Posts: 4
hello my name is Joonhee and I'm from South Korea

I am working my project with GTK and this is my first time using GTK

What I want to figure out is.. when you connect function to signal you can pass parameter to callback function

like this g_signal_connect_swapped(G_OBJECT(something), "signal", G_CALLBACK(func), (gpointer) param)

suppose "func" need one int parameter 'value' and I want to pass this value through 'param'

and the param value will change after program execution.

but when the signal is emitted, the func doesn't know the changed value of param. func is executed with initial param value,

which is not what i intended. So is there any way that I can delay binding of param and func? so func can catch the latest value of param

I'm sorry that my english is not good. Please help me


Top
 Profile  
 
 Post subject: Re: Passing parameters in the callback function
PostPosted: Thu Nov 01, 2012 11:24 pm 
Offline
Never Seen the Sunlight

Joined: Thu Mar 24, 2011 2:10 pm
Posts: 328
Location: Sydney, Australia
First thing is the case for int is different to other cases. In order to pass an int you need to use the glib macros to cast to gpointer GINT_TO_POINTER (and again back from it inside the callback function GPOINTER_TO_INT).
jhl0824 wrote:
and the param value will change after program execution.

but when the signal is emitted, the func doesn't know the changed value of param.

I don't see how this can be the case. The value passed to the function is the value of the int at the exact time the callback is made, not its initialised value.

Can you give more information to help me clarify exactly what you are doing? what is this int? How have you set it up? What examples do you have of it not knowing the changed value? Who is making the change and how (e.g. is it the user or the code that is doing the change etc.)? Maybe your problem is elsewhere. E.g. if you set up a spin button and initialise it to param and then change the spin button from the GUI then param is not actually changed - you need to actually read the value of the spin button back into param.

Also note that all the gtk function calls you make are not processed immediately, but are placed in a queue to be processed when your code reaches the gtk_main call. If your code cannot reach gtk_main while you are making GUI changes then it won't know about those changes.


Top
 Profile  
 
 Post subject: Re: Passing parameters in the callback function
PostPosted: Fri Nov 02, 2012 5:25 am 
Offline

Joined: Thu Nov 01, 2012 4:41 pm
Posts: 4
Thanks for your replay Paul. I really appriciated your comment.

Here is part of my code

g_signal_connect_swapped(G_OBJECT(button1), "clicked", G_CALLBACK(make_run), (gpointer) "./data/source.bin");
g_signal_connect_swapped(G_OBJECT(button2), "clicked", G_CALLBACK(merge_run), GINT_TO_POINTER (Glb_Number_of_Runs));

my program is about sorting data with merge sort algorithm, and I made it to run in the console mode(CUI). I'm trying to change this

into GUI version using GTK+

when the button1 is clicked, make_run function is executed, and inside function, global variable Glb_Number_of_Runs value changes.

And after button2 is clicked, merge_run function must be called with the changed value of Glb_Number_of_Runs. This works fine with my

console version. But with GTK+ version, correct value of Glb_Number_of_Runs is not fed to the merge_run function.

I debugged, and I think Glb_Number_of_Runs value is not a reachable(or available) after Gtk_Main() is executed.

So my guess is it just passes null value, which is 0 after converted to int. So actual function called is merge_run(0), which is not intended.

I wonder what is the problem..


Top
 Profile  
 
 Post subject: Re: Passing parameters in the callback function
PostPosted: Fri Nov 02, 2012 8:32 am 
Offline
Never Seen the Sunlight

Joined: Thu Mar 24, 2011 2:10 pm
Posts: 328
Location: Sydney, Australia
If Glb_Number_of_Runs is a global than why are you bothering passing it to a function? If it's a global variable than its scope should be such that it can't be unreachable. You'd be getting compilation warnings otherwise. By global I take it you have it declared outside and above each relevant function.

Could you present all of the relevant features of your code? (declarations of relevant variables/functions, places where Glb_Number_of_Runs is accessed/modified)


Top
 Profile  
 
 Post subject: Re: Passing parameters in the callback function
PostPosted: Fri Nov 02, 2012 12:29 pm 
Offline

Joined: Thu Nov 01, 2012 4:41 pm
Posts: 4
Thanks for your fast feedback Paul. I just removed the parameter for the merge_run() and it works fine.

But here is another problem. I'm trying to use horizontal slider to adjust some global variable and my code is below :
Code:
int main(int argc, char *argv[])
{
   GtkWidget *window, *vbox, *table, *label1, *label2, *label3;
   GtkWidget *scale_in, *scale_out, *scale_assist;
   GtkWidget *button1, *button2, *button3, *button4;

   gtk_init(&argc, &argv);

   window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
   gtk_window_set_title(GTK_WINDOW(window), "Optimizer");
   gtk_container_set_border_width(GTK_CONTAINER(window),10);
   gtk_widget_set_size_request(window, -1, -1);
//   gtk_window_set_resizable(GTK_WINDOW(window),false);
   gtk_window_set_icon_from_file(GTK_WINDOW(window),"SSD.png", NULL);


   g_signal_connect(G_OBJECT(window),"destroy",G_CALLBACK(destroy),NULL);

   vbox = gtk_vbox_new(false, 5); // 각 버튼 사이의 공간을 나타냄(버튼의 개수가 아니다)


   label1 = gtk_label_new("Input Buffer Size");
   label2 = gtk_label_new("Output Buffer Size");
   label3 = gtk_label_new("Assist Buffer Size");

   scale_in = gtk_hscale_new_with_range(0.0,10.0,1.0);
   scale_out = gtk_hscale_new_with_range(4.0,50.0,1.0);
   scale_assist = gtk_hscale_new_with_range(2.0,50.0,1.0);

   gtk_scale_set_digits(GTK_SCALE(scale_in), 0);
   gtk_scale_set_digits(GTK_SCALE(scale_out), 0);
   gtk_scale_set_digits(GTK_SCALE(scale_assist), 0);

   gtk_scale_set_value_pos(GTK_SCALE(scale_in), GTK_POS_RIGHT);
   gtk_scale_set_value_pos(GTK_SCALE(scale_out), GTK_POS_RIGHT);
   gtk_scale_set_value_pos(GTK_SCALE(scale_assist), GTK_POS_RIGHT);

   table = gtk_table_new(3,2,true);
   gtk_table_attach(GTK_TABLE(table), label1, 0,1,0,1,GTK_EXPAND, GTK_SHRINK, 0, 0);
   gtk_table_attach(GTK_TABLE(table), label2, 0,1,1,2,GTK_EXPAND, GTK_SHRINK, 0, 0);
   gtk_table_attach(GTK_TABLE(table), label3, 0,1,2,3,GTK_EXPAND, GTK_SHRINK, 0, 0);
   gtk_table_attach(GTK_TABLE(table), scale_in, 1,2,0,1,GTK_EXPAND, GTK_SHRINK, 0, 0);
   gtk_table_attach(GTK_TABLE(table), scale_out, 1,2,1,2,GTK_EXPAND, GTK_SHRINK, 0, 0);
   gtk_table_attach(GTK_TABLE(table), scale_assist, 1,2,2,3,GTK_EXPAND, GTK_SHRINK, 0, 0);

   gtk_table_set_row_spacings(GTK_TABLE(table), 5);
   gtk_table_set_col_spacings(GTK_TABLE(table), 5);

   button1 = gtk_button_new_with_label("Create Run files");
   button2 = gtk_button_new_with_label("Merge Run files");
   button3 = gtk_button_new_with_label("Create Run files with Orders");
   button4 = gtk_button_new_with_label("Merge Run files with Orders");

   gtk_box_pack_start_defaults(GTK_BOX(vbox), table);
   gtk_box_pack_start_defaults(GTK_BOX(vbox), button1);
   gtk_box_pack_start_defaults(GTK_BOX(vbox), button2);
   gtk_box_pack_start_defaults(GTK_BOX(vbox), button3);
   gtk_box_pack_start_defaults(GTK_BOX(vbox), button4);

   g_signal_connect_swapped(G_OBJECT(button1), "clicked", G_CALLBACK(make_run), (gpointer) "./data/source.bin");
   g_signal_connect_swapped(G_OBJECT(button2), "clicked", G_CALLBACK(merge_run), NULL);
   g_signal_connect_swapped(G_OBJECT(button3), "clicked", G_CALLBACK(make_run_order), (gpointer) "./data/source.bin");
   g_signal_connect_swapped(G_OBJECT(button4), "clicked", G_CALLBACK(merge_run_read_order_overlap), NULL);

   gtk_container_add(GTK_CONTAINER(window), vbox);
   gtk_widget_show_all(window);

   gtk_main();
   return 0;
}

When I compile the program, the scale slider is too small(I attached screenshot of this). I cannot adjust any value with this 0-length slider lol...

I have no idea why this is happening.


Attachments:
screenshot.png
screenshot.png [ 30.16 KiB | Viewed 762 times ]
Top
 Profile  
 
 Post subject: Re: Passing parameters in the callback function
PostPosted: Fri Nov 02, 2012 10:51 pm 
Offline
Never Seen the Sunlight

Joined: Thu Mar 24, 2011 2:10 pm
Posts: 328
Location: Sydney, Australia
Fast feedback is a convenience of having similar time-zones.

I think that what is happening is because of the SHRINK flag in the table, the scale is getting shrunk to its minimum size (zero length). Removing this might fix things. If not then another alternative (and one that you may find preferable anyway) is to use a spin button (the following example has the same adjustment as your scale but you can adjust it by 1 or 5 depending on the button press).
Code:
   GtkAdjustment *adj;
   ...
   adj=(GtkAdjustment*) gtk_adjustment_new(2, 0, 10, 1.0, 5.0, 0.0);
   scale_in=gtk_spin_button_new(adj, 0, 0);
   gtk_table_attach(GTK_TABLE(table), scale_in, 1, 2, 0, 1, GTK_FILL|GTK_SHRINK|GTK_EXPAND, GTK_FILL|GTK_SHRINK|GTK_EXPAND, 0, 0);
   gtk_widget_show(scale_in);

By the way, something important the tutorials never tell anyone is that whenever you have a label for a different widget you need to set up atk relationships. Similarly if there are any other relationships that gtk wouldn't know about automatically (though labelling is the main one). ATK does all the accessibility stuff, e.g. useful stuff like screen readers, voice activation etc. Sure not everyone make use of this functionality, but for those that rely on it, its incredibly important that software be designed to allow it.
Code:
   atk_widget=gtk_widget_get_accessible(scale_in);
   atk_label=gtk_widget_get_accessible(GTK_WIDGET(label1));
   atk_object_add_relationship(atk_label, ATK_RELATION_LABEL_FOR, atk_widget);
   atk_object_add_relationship(atk_widget, ATK_RELATION_LABELLED_BY, atk_label);


Top
 Profile  
 
 Post subject: Re: Passing parameters in the callback function
PostPosted: Sat Nov 03, 2012 2:38 pm 
Offline

Joined: Thu Nov 01, 2012 4:41 pm
Posts: 4
Finally the problem solved. I used horizontal box instead of table, and the scale works fine with it.

And about atk relationships.. as you said, tutorial never told me about it. Thank you for letting me know this secret.

I really appreciate your replay. I couldn't have come this far if there wasn't your help :)


Top
 Profile  
 
 Post subject: Re: Passing parameters in the callback function
PostPosted: Sat Nov 03, 2012 11:12 pm 
Offline
Never Seen the Sunlight

Joined: Thu Mar 24, 2011 2:10 pm
Posts: 328
Location: Sydney, Australia
The downside to using horizontal box will be that the alignment is not consistent. E.g. in a grid the column width is the same for each row. In a series of hboxes this cannot be guaranteed. Better than a zero width slider of course, but still less than ideal. You may get similar issues if you use two vboxes instead. It would be best to try and getting it working as a table. Try replacing GTK_EXPAND with GTK_EXPAND|GTK_FILL for your table attach calls and see if that helps.


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

All times are UTC


Who is online

Users browsing this forum: Google [Bot] and 6 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