📄 gtk_tut.sgml
字号:
<p>Before we look in detail at <em>helloworld</em>, we'll discuss signalsand callbacks. GTK is an event driven toolkit, which means it willsleep in gtk_main until an event occurs and control is passed to theappropriate function.This passing of control is done using the idea of "signals". When anevent occurs, such as the press of a mouse button, the appropriatesignal will be "emitted" by the widget that was pressed. This is howGTK does most of its useful work. There are a set of signals that allwidgets inherit, such as "destroy", and there are signals that arewidget specific, such as "toggled" on a toggle button.To make a button perform an action, we set up a signal handler tocatch these signals and call the appropriate function. This is done byusing a function such as:<tscreen><verb>gint gtk_signal_connect( GtkObject *object, gchar *name, GtkSignalFunc func, gpointer func_data );</verb></tscreen>Where the first argument is the widget which will be emitting thesignal, and the second, the name of the signal you wish to catch. Thethird is the function you wish to be called when it is caught, and thefourth, the data you wish to have passed to this function.The function specified in the third argument is called a "callbackfunction", and should generally be of the form:<tscreen><verb>void callback_func( GtkWidget *widget, gpointer callback_data );</verb></tscreen>Where the first argument will be a pointer to the widget that emittedthe signal, and the second, a pointer to the data given as the lastargument to the gtk_signal_connect() function as shown above.Note that the above form for a signal callback function declaration isonly a general guide, as some widget specific signals generatedifferent calling parameters. For example, the GtkCList "select_row"signal provides both row and column parameters.Another call used in the <em>helloworld</em> example, is:<tscreen><verb>gint gtk_signal_connect_object( GtkObject *object, gchar *name, GtkSignalFunc func, GtkObject *slot_object );</verb></tscreen>gtk_signal_connect_object() is the same as gtk_signal_connect() exceptthat the callback function only uses one argument, a pointer to a GTKobject. So when using this function to connect signals, the callbackshould be of the form:<tscreen><verb>void callback_func( GtkObject *object );</verb></tscreen>Where the object is usually a widget. We usually don't setup callbacksfor gtk_signal_connect_object however. They are usually used to call aGTK function that accepts a single widget or object as an argument, asis the case in our <em>helloworld</em> example.The purpose of having two functions to connect signals is simply toallow the callbacks to have a different number of arguments. Manyfunctions in the GTK library accept only a single GtkWidget pointer asan argument, so you want to use the gtk_signal_connect_object() forthese, whereas for your functions, you may need to have additionaldata supplied to the callbacks.<!-- ----------------------------------------------------------------- --><sect1>Events<p>In addition to the signal mechanism described above, there are a setof <em>events</em> that reflect the X event mechanism. Callbacks mayalso be attached to these events. These events are:<itemize><item> event<item> button_press_event<item> button_release_event<item> motion_notify_event<item> delete_event<item> destroy_event<item> expose_event<item> key_press_event<item> key_release_event<item> enter_notify_event<item> leave_notify_event<item> configure_event<item> focus_in_event<item> focus_out_event<item> map_event<item> unmap_event<item> property_notify_event<item> selection_clear_event<item> selection_request_event<item> selection_notify_event<item> proximity_in_event<item> proximity_out_event<item> drag_begin_event<item> drag_request_event<item> drag_end_event<item> drop_enter_event<item> drop_leave_event<item> drop_data_available_event<item> other_event</itemize>In order to connect a callback function to one of these events, youuse the function gtk_signal_connect, as described above, using one ofthe above event names as the <tt/name/ parameter. The callbackfunction for events has a slightly different form than that forsignals:<tscreen><verb>void callback_func( GtkWidget *widget, GdkEvent *event, gpointer callback_data );</verb></tscreen>GdkEvent is a C <tt/union/ structure whose type will depend upon whichof the above events has occurred. In order for us to tell which eventhas been issued each of the possible alternatives has a <tt/type/parameter which reflects the event being issued. The other componentsof the event structure will depend upon the type of theevent. Possible values for the type are:<tscreen><verb> GDK_NOTHING GDK_DELETE GDK_DESTROY GDK_EXPOSE GDK_MOTION_NOTIFY GDK_BUTTON_PRESS GDK_2BUTTON_PRESS GDK_3BUTTON_PRESS GDK_BUTTON_RELEASE GDK_KEY_PRESS GDK_KEY_RELEASE GDK_ENTER_NOTIFY GDK_LEAVE_NOTIFY GDK_FOCUS_CHANGE GDK_CONFIGURE GDK_MAP GDK_UNMAP GDK_PROPERTY_NOTIFY GDK_SELECTION_CLEAR GDK_SELECTION_REQUEST GDK_SELECTION_NOTIFY GDK_PROXIMITY_IN GDK_PROXIMITY_OUT GDK_DRAG_BEGIN GDK_DRAG_REQUEST GDK_DROP_ENTER GDK_DROP_LEAVE GDK_DROP_DATA_AVAIL GDK_CLIENT_EVENT GDK_VISIBILITY_NOTIFY GDK_NO_EXPOSE GDK_OTHER_EVENT /* Deprecated, use filters instead */</verb></tscreen>So, to connect a callback function to one of these events we would usesomething like:<tscreen><verb>gtk_signal_connect( GTK_OBJECT(button), "button_press_event", GTK_SIGNAL_FUNC(button_press_callback), NULL);</verb></tscreen>This assumes that <tt/button/ is a GtkButton widget. Now, when themouse is over the button and a mouse button is pressed, the function<tt/button_press_callback/ will be called. This function may bedeclared as:<tscreen><verb>static gint button_press_event (GtkWidget *widget, GdkEventButton *event, gpointer data);</verb></tscreen>Note that we can declare the second argument as type<tt/GdkEventButton/ as we know what type of event will occur for thisfunction to be called.The value returned from this function indicates whether the eventshould be propagated further by the GTK event handlingmechanism. Returning TRUE indicates that the event has been handled,and that it should not propagate further. Returning FALSE continuesthe normal event handling. See the section on<ref id="sec_Adv_Events_and_Signals"name="Advanced Event and Signal Handling"> for more details on thispropagation process.For details on the GdkEvent data types, see the appendix entitled<ref id="sec_GDK_Event_Types" name="GDK Event Types">.<!-- ----------------------------------------------------------------- --><sect1>Stepping Through Hello World<p>Now that we know the theory behind this, lets clarify by walking through the example <em>helloworld</em> program.Here is the callback function that will be called when the button is"clicked". We ignore both the widget and the data in this example, butit is not hard to do things with them. The next example will use thedata argument to tell us which button was pressed.<tscreen><verb>void hello( GtkWidget *widget, gpointer data ){ g_print ("Hello World\n");}</verb></tscreen>The next callback is a bit special. The "delete_event" occurs when thewindow manager sends this event to the application. We have a choicehere as to what to do about these events. We can ignore them, makesome sort of response, or simply quit the application.The value you return in this callback lets GTK know what action totake. By returning TRUE, we let it know that we don't want to havethe "destroy" signal emitted, keeping our application running. Byreturning FALSE, we ask that "destroy" is emitted, which in turn willcall our "destroy" signal handler.<tscreen><verb>gint delete_event( GtkWidget *widget, GdkEvent *event, gpointer data ){ g_print ("delete event occurred\n"); return (TRUE); }</verb></tscreen>Here is another callback function which causes the program to quit bycalling gtk_main_quit(). This function tells GTK that it is to exitfrom gtk_main when control is returned to it.<tscreen><verb>void destroy( GtkWidget *widget, gpointer data ){ gtk_main_quit ();}</verb></tscreen>I assume you know about the main() function... yes, as with otherapplications, all GTK applications will also have one of these.<tscreen><verb>int main( int argc, char *argv[] ){</verb></tscreen>This next part, declares a pointer to a structure of typeGtkWidget. These are used below to create a window and a button.<tscreen><verb> GtkWidget *window; GtkWidget *button;</verb></tscreen>Here is our gtk_init again. As before, this initializes the toolkit,and parses the arguments found on the command line. Any argument itrecognizes from the command line, it removes from the list, andmodifies argc and argv to make it look like they never existed,allowing your application to parse the remaining arguments.<tscreen><verb> gtk_init (&argc, &argv);</verb></tscreen>Create a new window. This is fairly straight forward. Memory isallocated for the GtkWidget *window structure so it now points to avalid structure. It sets up a new window, but it is not displayeduntil we call gtk_widget_show(window) near the end of our program.<tscreen><verb> window = gtk_window_new (GTK_WINDOW_TOPLEVEL);</verb></tscreen>Here is an example of connecting a signal handler to an object, inthis case, the window. Here, the "destroy" signal is caught. This isemitted when we use the window manager to kill the window (and wereturn FALSE in the "delete_event" handler), or when we use thegtk_widget_destroy() call passing in the window widget as the objectto destroy. By setting this up, we handle both cases with a singlecall. Here, it just calls the destroy() function defined above with aNULL argument, which quits GTK for us.The GTK_OBJECT and GTK_SIGNAL_FUNC are macros that perform typecasting and checking for us, as well as aid the readability of thecode.<tscreen><verb> gtk_signal_connect (GTK_OBJECT (window), "destroy", GTK_SIGNAL_FUNC (destroy), NULL);</verb></tscreen>This next function is used to set an attribute of a container object.This just sets the window so it has a blank area along the inside ofit 10 pixels wide where no widgets will go. There are other similarfunctions which we will look at in the section on<ref id="sec_setting_widget_attributes" name="Setting Widget Attributes">And again, GTK_CONTAINER is a macro to perform type casting.<tscreen><verb> gtk_container_set_border_width (GTK_CONTAINER (window), 10);</verb></tscreen>This call creates a new button. It allocates space for a new GtkWidgetstructure in memory, initializes it, and makes the button pointerpoint to it. It will have the label "Hello World" on it whendisplayed.<tscreen><verb> button = gtk_button_new_with_label ("Hello World");</verb></tscreen>Here, we take this button, and make it do something useful. We attacha signal handler to it so when it emits the "clicked" signal, ourhello() function is called. The data is ignored, so we simply pass inNULL to the hello() callback function. Obviously, the "clicked" signalis emitted when we click the button with our mouse pointer.<tscreen><verb> gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (hello), NULL);</verb></tscreen>We are also going to use this button to exit our program. This willillustrate how the "destroy" signal may come from either the windowmanager, or our program. When the button is "clicked", same as above,it calls the first hello() callback function, and then this one in theorder they are set up. You may have as many callback functions as youneed, and all will be executed in the order you connectedthem. Because the gtk_widget_destroy() function accepts only aGtkWidget *widget as an argument, we use thegtk_signal_connect_object() function here instead of straightgtk_signal_connect().<tscreen><verb> gtk_signal_connect_object (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (gtk_widget_destroy), GTK_OBJECT (window));</verb></tscreen>This is a packing call, which will be explained in depth later on. Butit is fairly easy to understand. It simply tells GTK that the buttonis to be placed in the window where it will be displayed. Note that aGTK container can only contain one widget. There are other widgets,that are described later, which are designed to layout multiplewidgets in various ways. <tscreen><verb> gtk_container_add (GTK_CONTAINER (window), button);</verb></tscreen>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -