RE: g_signal_connect




the g_signal_connect works like what?
   g_signal_connect(GTK_WIDGET(widget),
       signal("clicked"),<br>G_CALLBACK(Function),
       (gpointer) "Data");
but the callbacks functions have the GtkWidget *Widget as a 1st
parameter, and... well, i simply don't get it. =)

Lots of answers, means lots of chances to understand.  But I haven't seen one that really explains WHY those 
arguments are there, and what they're useful for.  So I'll throw in my 2000c worth...  ;)

An "object" is a cluster of information and traits, related to a specific purpose.  A button, for example, 
has a rectanglular area on the screen, an appearance that it knows how to draw, a child widget that it 
contains, and a purpose, which it fulfills via callback functions.  All these things it knows about and can 
do, are encapsulated within the concept of an object.  Some traits and capabilities (represented by the API 
functions), such as its rectangular area are inherited from a "parent" object.  A check button, for instance, 
has all the traits of a toggle button, which is similar to a standard button but with slightly different 
symantics.  (The "clicked" callback is a feature of the GtkButton.)

Now, if you've got three buttons on the screen, and they all were using the same callback function, how would 
you know which one the user clicked on?  To answer that question, two extra arguments are passed besides the 
ones that the "clicked" signal defines.  One, is a pointer to the actual button that was clicked on 
(GtkWidget *widget), and the other is an argument of your choosing.  A user data pointer.  The widget pointer 
allows you to easily reach back into the widget that caused the clicked signal, for instance, to fetch some 
data that was attached to it, or even to change the colour of the text label, or make it insensitive, or 
whatever.  The user pointer would usually carry information that makes that button's purpose different from 
the other two.  Maybe it's the Play button on a music player, rather than the Stop button.  They're both 
buttons.  And with i18n, you can't even be certain what the buttons text will be.  So the only way to tell 
them apart, is with the user
  data.

Since you've got a play and a stop button, you might want only one to be sensitive (available) at a time.  So 
you might pass the pointer to the other one as the user data.  Whichever one was clicked on, you can 
insensitise using the "widget" pointer.  And the other one you can make sensitive through the user data.  
There are other things you can do too.  Say you want to make the button simply cease to exist as soon as it 
gets clicked.  You could use gtk_widget_destroy() as the callback function.  I once did something like that 
with log messages, each built as a button that destroyed itself when clicked (or when a timer expired).  The 
timer ID was attached as data to the button widget, and destroyed in the widgets own destroy signal handler.  
So no matter which way it happened, everything was cleaned up automatically, and once the button was made I 
didn't have to keep any pointers to it, or any extra data anywhere.  The entire log message, and the option 
for the user to get ri
 d or it or just wait until it went away itself, was all wrapped up in a set-and-forget parcel.

On the other hand, you might want to make it destroy the entire window when it gets clicked.  A cancel button 
on a dialog box or preferences page, for instance.  You can use the same trick, passing gtk_widget_destroy() 
as the callback.  But instead of allowing it to destroy the widget itself, you pass the pointer to the window 
as the user data, and use the g_signal_connect_swapped() method instead.  This puts the user data first, and 
the widget pointer last.  gtk_widget_destoy() only looks at the first argument, so it destroys the entire 
window instead of a single widget.  I frequently attach a windows close signal directly to 
gtk_widget_destroy() using g_signal_connect(), and use the very technique I just mentioned on a Close/Cancel 
button to just make the whole thing go away, in exactly the same way.  There are "other" ways of doing it, 
such as if you need to ask the user if they're sure before you close it.  But for a simple task like getting 
rid of a small message box, us
 e a simple solution.


A signal is the means by which an object (such as a button) tells you something has happened.  And the widget 
and user data pointers are the means by which it tells you which specific widget it was (among however many 
of them might be there), and what its purpose for being there was.  You don't have to use either, for 
instance, if there's only one widget that will ever call that callback function for one particular reason.  
But in the case of gtk_widget_destroy(), it has no idea which widget was calling it unless you tell it.  And 
in the case of the log messages, each message was put up as a button, as it happened at run-time.  There was 
no way to predict how many buttons there might me, or even whether there would be any at all.  And since the 
GtkVBox they were being packed into was already a list of them all, there wasn't much point duplicating the 
effort by creating and maintaining my own list, when the widgets callbacks contained all the information 
needed to perform the 
 buttons purpose (which was simply to get rid of itself and the associated timer).


Fredderic

_______________________________________________
Join Excite! - http://www.excite.com
The most personalized portal on the Web!



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