gtk_tut.sgml
来自「gtk1.2的教程」· SGML 代码 · 共 1,828 行 · 第 1/5 页
SGML
1,828 行
</verb></tscreen>This is a packing call, which will be explained in depth later on in<ref id="sec_packing_widgets" name="Packing Widgets">. But it isfairly easy to understand. It simply tells GTK that the button is tobe placed in the window where it will be displayed. Note that a GTKcontainer can only contain one widget. There are other widgets, thatare described later, which are designed to layout multiple widgets invarious ways. <tscreen><verb> gtk_container_add (GTK_CONTAINER (window), button);</verb></tscreen>Now we have everything set up the way we want it to be. With all thesignal handlers in place, and the button placed in the window where itshould be, we ask GTK to "show" the widgets on the screen. The windowwidget is shown last so the whole window will pop up at once ratherthan seeing the window pop up, and then the button form inside ofit. Although with such a simple example, you'd never notice.<tscreen><verb> gtk_widget_show (button); gtk_widget_show (window);</verb></tscreen>And of course, we call gtk_main() which waits for events to come fromthe X server and will call on the widgets to emit signals when theseevents come.<tscreen><verb> gtk_main ();</verb></tscreen>And the final return. Control returns here after gtk_quit() is called.<tscreen><verb> return (0);</verb></tscreen>Now, when we click the mouse button on a GTK button, the widget emitsa "clicked" signal. In order for us to use this information, ourprogram sets up a signal handler to catch that signal, whichdispatches the function of our choice. In our example, when the buttonwe created is "clicked", the hello() function is called with a NULLargument, and then the next handler for this signal is called. Thiscalls the gtk_widget_destroy() function, passing it the window widgetas its argument, destroying the window widget. This causes the windowto emit the "destroy" signal, which is caught, and calls our destroy()callback function, which simply exits GTK.Another course of events is to use the window manager to kill thewindow, which will cause the "delete_event" to be emitted. This willcall our "delete_event" handler. If we return TRUE here, the windowwill be left as is and nothing will happen. Returning FALSE will causeGTK to emit the "destroy" signal which of course calls the "destroy"callback, exiting GTK.<!-- ***************************************************************** --><sect>Moving On<!-- ***************************************************************** --><!-- ----------------------------------------------------------------- --><sect1>Data Types<p>There are a few things you probably noticed in the previous examplesthat need explaining. The gint, gchar, etc. that you see are typedefsto int and char, respectively, that are part of the GLlib system. Thisis done to get around that nasty dependency on the size of simple datatypes when doing calculations.A good example is "gint32" which will be typedef'd to a 32 bit integerfor any given platform, whether it be the 64 bit alpha, or the 32 biti386. The typedefs are very straightforward and intuitive. They areall defined in glib/glib.h (which gets included from gtk.h).You'll also notice GTK's ability to use GtkWidget when the functioncalls for an Object. GTK is an object oriented design, and a widgetis an object.<!-- ----------------------------------------------------------------- --><sect1>More on Signal Handlers<p>Lets take another look at the gtk_signal_connect declaration.<tscreen><verb>gint gtk_signal_connect( GtkObject *object, gchar *name, GtkSignalFunc func, gpointer func_data );</verb></tscreen>Notice the gint return value? This is a tag that identifies yourcallback function. As stated above, you may have as many callbacks persignal and per object as you need, and each will be executed in turn,in the order they were attached.This tag allows you to remove this callback from the list by using:<tscreen><verb>void gtk_signal_disconnect( GtkObject *object, gint id );</verb></tscreen>So, by passing in the widget you wish to remove the handler from, andthe tag returned by one of the signal_connect functions, you candisconnect a signal handler.You can also temporarily disable signal handlers with thegtk_signal_handler_block() and gtk_signal_handler_unblock() family offunctions.<tscreen><verb>void gtk_signal_handler_block( GtkObject *object, guint handler_id );void gtk_signal_handler_block_by_func( GtkObject *object, GtkSignalFunc func, gpointer data );void gtk_signal_handler_block_by_data( GtkObject *object, gpointer data );void gtk_signal_handler_unblock( GtkObject *object, guint handler_id );void gtk_signal_handler_unblock_by_func( GtkObject *object, GtkSignalFunc func, gpointer data );void gtk_signal_handler_unblock_by_data( GtkObject *object, gpointer data);</verb></tscreen><!-- ----------------------------------------------------------------- --><sect1>An Upgraded Hello World<p>Let's take a look at a slightly improved <em>helloworld</em> withbetter examples of callbacks. This will also introduce us to our nexttopic, packing widgets.<tscreen><verb>/* example-start helloworld2 helloworld2.c */#include <gtk/gtk.h>/* Our new improved callback. The data passed to this function * is printed to stdout. */void callback( GtkWidget *widget, gpointer data ){ g_print ("Hello again - %s was pressed\n", (char *) data);}/* another callback */gint delete_event( GtkWidget *widget, GdkEvent *event, gpointer data ){ gtk_main_quit(); return(FALSE);}int main( int argc, char *argv[] ){ /* GtkWidget is the storage type for widgets */ GtkWidget *window; GtkWidget *button; GtkWidget *box1; /* This is called in all GTK applications. Arguments are parsed * from the command line and are returned to the application. */ gtk_init (&argc, &argv); /* Create a new window */ window = gtk_window_new (GTK_WINDOW_TOPLEVEL); /* This is a new call, which just sets the title of our * new window to "Hello Buttons!" */ gtk_window_set_title (GTK_WINDOW (window), "Hello Buttons!"); /* Here we just set a handler for delete_event that immediately * exits GTK. */ gtk_signal_connect (GTK_OBJECT (window), "delete_event", GTK_SIGNAL_FUNC (delete_event), NULL); /* Sets the border width of the window. */ gtk_container_set_border_width (GTK_CONTAINER (window), 10); /* We create a box to pack widgets into. This is described in detail * in the "packing" section. The box is not really visible, it * is just used as a tool to arrange widgets. */ box1 = gtk_hbox_new(FALSE, 0); /* Put the box into the main window. */ gtk_container_add (GTK_CONTAINER (window), box1); /* Creates a new button with the label "Button 1". */ button = gtk_button_new_with_label ("Button 1"); /* Now when the button is clicked, we call the "callback" function * with a pointer to "button 1" as its argument */ gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (callback), (gpointer) "button 1"); /* Instead of gtk_container_add, we pack this button into the invisible * box, which has been packed into the window. */ gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0); /* Always remember this step, this tells GTK that our preparation for * this button is complete, and it can now be displayed. */ gtk_widget_show(button); /* Do these same steps again to create a second button */ button = gtk_button_new_with_label ("Button 2"); /* Call the same callback function with a different argument, * passing a pointer to "button 2" instead. */ gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (callback), (gpointer) "button 2"); gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0); /* The order in which we show the buttons is not really important, but I * recommend showing the window last, so it all pops up at once. */ gtk_widget_show(button); gtk_widget_show(box1); gtk_widget_show (window); /* Rest in gtk_main and wait for the fun to begin! */ gtk_main (); return(0);}/* example-end */</verb></tscreen>Compile this program using the same linking arguments as our firstexample. You'll notice this time there is no easy way to exit theprogram, you have to use your window manager or command line to killit. A good exercise for the reader would be to insert a third "Quit"button that will exit the program. You may also wish to play with theoptions to gtk_box_pack_start() while reading the next section. Tryresizing the window, and observe the behavior.Just as a side note, there is another useful define forgtk_window_new() - <tt/GTK_WINDOW_DIALOG/. This interacts with thewindow manager a little differently and should be used for transientwindows.<!-- ***************************************************************** --><sect>Packing Widgets <label id="sec_packing_widgets"><!-- ***************************************************************** --><p>When creating an application, you'll want to put more than one widgetinside a window. Our first <em>helloworld</em> example only used onewidget so we could simply use a gtk_container_add call to "pack" thewidget into the window. But when you want to put more than one widgetinto a window, how do you control where that widget is positioned?This is where packing comes in.<!-- ----------------------------------------------------------------- --><sect1>Theory of Packing Boxes<p>Most packing is done by creating boxes as in the example above. Theseare invisible widget containers that we can pack our widgets intowhich come in two forms, a horizontal box, and a vertical box. Whenpacking widgets into a horizontal box, the objects are insertedhorizontally from left to right or right to left depending on the callused. In a vertical box, widgets are packed from top to bottom or viceversa. You may use any combination of boxes inside or beside otherboxes to create the desired effect.To create a new horizontal box, we use a call to gtk_hbox_new(), andfor vertical boxes, gtk_vbox_new(). The gtk_box_pack_start() andgtk_box_pack_end() functions are used to place objects inside of thesecontainers. The gtk_box_pack_start() function will start at the topand work its way down in a vbox, and pack left to right in an hbox.gtk_box_pack_end() will do the opposite, packing from bottom to top ina vbox, and right to left in an hbox. Using these functions allows usto right justify or left justify our widgets and may be mixed in anyway to achieve the desired effect. We will use gtk_box_pack_start() inmost of our examples. An object may be another container or awidget. In fact, many widgets are actually containers themselves,including the button, but we usually only use a label inside a button.By using these calls, GTK knows where you want to place your widgetsso it can do automatic resizing and other nifty things. There are alsoa number of options as to how your widgets should be packed. As youcan imagine, this method gives us a quite a bit of flexibility whenplacing and creating widgets.<!-- ----------------------------------------------------------------- --><sect1>Details of Boxes<p>Because of this flexibility, packing boxes in GTK can be confusing atfirst. There are a lot of options, and it's not immediately obvious howthey all fit together. In the end, however, there are basically fivedifferent styles.<? <CENTER> ><?<IMG SRC="gtk_tut_packbox1.gif" VSPACE="15" HSPACE="10" WIDTH="528"HEIGHT="235" ALT="Box Packing Example Image">><? </CENTER> >Each line contains one horizontal box (hbox) with several buttons. Thecall to gtk_box_pack is shorthand for the call to pack each of thebuttons into the hbox. Each of the buttons is packed into the hbox thesame way (i.e., same arguments to the gtk_box_pack_start() function).This is the declaration of the gtk_box_pack_start function.<tscreen><verb>void gtk_box_pack_start( GtkBox *box, GtkWidget *child, gint expand, gint fill, gint padding );</verb></tscreen>The first argument is the box you are packing the object into, thesecond is the object. The objects will all be buttons for now, sowe'll be packing buttons into boxes.The expand argument to gtk_box_pack_start() and gtk_box_pack_end()controls whether the widgets are laid out in the box to fill in allthe extra space in the box so the box is expanded to fill the areaallotted to it (TRUE); or the box is shrunk to just fit the widgets(FALSE). Setting expand to FALSE will allow you to do right and leftjustification of your widgets. Otherwise, they will all expand to fitinto the box, and the same effect could be achieved by using only oneof gtk_box_pack_start or gtk_box_pack_end.The fill argument to the gtk_box_pack functions control whether theextra space is allocated to the objects themselves (TRUE), or as extrapadding in the box around these objects (FALSE). It only has an effectif the expand argument is also TRUE.When creating a new box, the function looks like this:<tscreen><verb>GtkWidget *gtk_hbox_new (gint homogeneous, gint spacing);</verb></tscreen>The homogeneous argument to gtk_hbox_new (and the same forgtk_vbox_new) controls whether each object in the box has the samesize (i.e., the same width in an hbox, or the same height in avbox). If it is set, the gtk_box_pack routines function essentiallyas if the <tt/expand/ argument was always turned on.What's the difference between spacing (set when the box is created)and padding (set when elements are packed)? Spacing is added betweenobjects, and padding is added on either side of an object. Thefollowing figure should make it clearer:<? <CENTER> ><?<IMG ALIGN="center" SRC="gtk_tut_packbox2.gif" WIDTH="509"HEIGHT="213" VSPACE="15" HSPACE="10"
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?