2. 开始 第 一件要做的是当然是取得一份GTK的原始码并且安装进您的系统中. 您可以从GIMP取得一份发行版, 或者是从Peter Mattis\"s的\"家中\" ftp.xcf.berkely.edu/pub/pmattis(however, it has been changed to ftp.gimp.org)取得一份. GTK使用GNU的autoconf来设定. 一但您解开档案, 输入configure --help来看看选项表列.
下 一个函数是用来设定container物件的属性. This just sets the window so it has a blank area along the inside of it 10 pixels wide where no widgets will go. There are other similar functions which we will look at in the section on Setting Widget Attributes
And again, GTK_CONTAINER is a macro to perform type casting.
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);
/* 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 be displayed now. */ 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\");
/* 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 ();
/* Make a new hbox filled with button-labels. Arguments for the * variables we\"re interested are passed in to this function. * We do not show the box, but do show everything inside. */ GtkWidget *make_box (gint homogeneous, gint spacing, gint expand, gint fill, gint padding) { GtkWidget *box; GtkWidget *button; char padstr[80];
/* create a new hbox with the appropriate homogeneous and spacing * settings */ box = gtk_hbox_new (homogeneous, spacing);
/* create a series of buttons with the appropriate settings */ button = gtk_button_new_with_label (\"gtk_box_pack\"); gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding); gtk_widget_show (button);
/* create a button with the label depending on the value of * expand. */ if (expand == TRUE) button = gtk_button_new_with_label (\"TRUE,\"); else button = gtk_button_new_with_label (\"FALSE,\");
/* This is the same as the button creation for \"expand\" * above, but uses the shorthand form. */ button = gtk_button_new_with_label (fill ? \"TRUE,\" : \"FALSE,\"); gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding); gtk_widget_show (button);
if (argc != 2) { fprintf (stderr, \"usage: packbox num, where num is 1, 2, or 3.\\n\"); /* this just does cleanup in GTK, and exits with an exit status of 1. */ gtk_exit (1); }
/* You should always remember to connect the destroy signal to the * main window. This is very important for proper intuitive * behavior */ gtk_signal_connect (GTK_OBJECT (window), \"destroy\", GTK_SIGNAL_FUNC (destroy), NULL); gtk_container_border_width (GTK_CONTAINER (window), 10);
/* We create a vertical box (vbox) to pack the horizontal boxes into. * This allows us to stack the horizontal boxes filled with buttons one * on top of the other in this vbox. */ box1 = gtk_vbox_new (FALSE, 0);
/* which example to show. These correspond to the pictures above. */ switch (which) { case 1: /* create a new label. */ label = gtk_label_new (\"gtk_hbox_new (FALSE, 0);\");
/* Align the label to the left side. We\"ll discuss this function and * others in the section on Widget Attributes. */ gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
/* Pack the label into the vertical box (vbox box1). Remember that * widgets added to a vbox will be packed one on top of the other in * order. */ gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
/* creates a separator, we\"ll learn more about these later, * but they are quite simple. */ separator = gtk_hseparator_new ();
/* pack the separator into the vbox. Remember each of these * widgets are being packed into a vbox, so they\"ll be stacked * vertically. */ gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5); gtk_widget_show (separator);
/* create another new label, and show it. */ label = gtk_label_new (\"gtk_hbox_new (TRUE, 0);\"); gtk_misc_set_alignment (GTK_MISC (label), 0, 0); gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0); gtk_widget_show (label);
/* another new separator. */ separator = gtk_hseparator_new (); /* The last 3 arguments to gtk_box_pack_start are: expand, fill, padding. */ gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5); gtk_widget_show (separator);
break;
case 2:
/* create a new label, remember box1 is a vbox as created * near the beginning of main() */ label = gtk_label_new (\"gtk_hbox_new (FALSE, 10);\"); gtk_misc_set_alignment (GTK_MISC (label), 0, 0); gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0); gtk_widget_show (label);
separator = gtk_hseparator_new (); /* The last 3 arguments to gtk_box_pack_start are: expand, fill, padding. */ gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5); gtk_widget_show (separator); break;
case 3:
/* This demonstrates the ability to use gtk_box_pack_end() to * right justify widgets. First, we create a new box as before. */ box2 = make_box (FALSE, 0, FALSE, FALSE, 0); /* create the label that will be put at the end. */ label = gtk_label_new (\"end\"); /* pack it using gtk_box_pack_end(), so it is put on the right side * of the hbox created in the make_box() call. */ gtk_box_pack_end (GTK_BOX (box2), label, FALSE, FALSE, 0); /* show the label. */ gtk_widget_show (label);
/* pack box2 into box1 (the vbox remember ? :) */ gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0); gtk_widget_show (box2);
/* a separator for the bottom. */ separator = gtk_hseparator_new (); /* this explicitly sets the separator to 400 pixels wide by 5 pixels * high. This is so the hbox we created will also be 400 pixels wide, * and the \"end\" label will be separated from the other labels in the * hbox. Otherwise, all the widgets in the hbox would be packed as * close together as possible. */ gtk_widget_set_usize (separator, 400, 5); /* pack the separator into the vbox (box1) created near the start * of main() */ gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5); gtk_widget_show (separator); }
/* Create another new hbox.. remember we can use as many as we need! */ quitbox = gtk_hbox_new (FALSE, 0);
/* setup the signal to destroy the window. Remember that this will send * the \"destroy\" signal to the window which will be caught by our signal * handler as defined above. */ gtk_signal_connect_object (GTK_OBJECT (button), \"clicked\", GTK_SIGNAL_FUNC (gtk_widget_destroy), GTK_OBJECT (window)); /* pack the button into the quitbox. * The last 3 arguments to gtk_box_pack_start are: expand, fill, padding. */ gtk_box_pack_start (GTK_BOX (quitbox), button, TRUE, FALSE, 0); /* pack the quitbox into the vbox (box1) */ gtk_box_pack_start (GTK_BOX (box1), quitbox, FALSE, FALSE, 0);
/* pack the vbox (box1) which now contains all our widgets, into the * main window. */ gtk_container_add (GTK_CONTAINER (window), box1);
/* and show everything left */ gtk_widget_show (button); gtk_widget_show (quitbox);
gtk_widget_show (box1); /* Showing the window last so everything pops up at once. */ gtk_widget_show (window);
/* And of course, our main function. */ gtk_main ();
/* control returns here when gtk_main_quit() is called, but not when * gtk_exit is used. */
/* This function rotates the position of the tabs */ void rotate_book (GtkButton *button, GtkNotebook *notebook) { gtk_notebook_set_tab_pos (notebook, (notebook->tab_pos +1) %4); }
/* Add/Remove the page tabs and the borders */ void tabsborder_book (GtkButton *button, GtkNotebook *notebook) { gint tval = FALSE; gint bval = FALSE; if (notebook->show_tabs == 0) tval = TRUE; if (notebook->show_border == 0) bval = TRUE;
/* Remove a page from the notebook */ void remove_book (GtkButton *button, GtkNotebook *notebook) { gint page;
page = gtk_notebook_current_page(notebook); gtk_notebook_remove_page (notebook, page); /* Need to refresh the widget -- This forces the widget to redraw itself. */ gtk_widget_draw(GTK_WIDGET(notebook), NULL); }
/* Create a new notebook, place the position of the tabs */ notebook = gtk_notebook_new (); gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_TOP); gtk_table_attach_defaults(GTK_TABLE(table), notebook, 0,6,0,1); gtk_widget_show(notebook);
/* lets append a bunch of pages to the notebook */ for (i=0; i < 5; i++) { sprintf(bufferf, \"Append Frame %d\", i+1); sprintf(bufferl, \"Page %d\", i+1);
/* now lets add a page to a specific spot */ checkbutton = gtk_check_button_new_with_label (\"Check me please!\"); gtk_widget_set_usize(checkbutton, 100, 75); gtk_widget_show (checkbutton);
int main (int argc, char *argv[]) { static GtkWidget *window; GtkWidget *scrolled_window; GtkWidget *table; GtkWidget *button; char buffer[32]; int i, j;
gtk_init (&argc, &argv);
/* Create a new dialog window for the scrolled window to be * packed into. A dialog is just like a normal window except it has a * vbox and a horizontal seperator packed into it. It\"s just a shortcut * for creating dialogs */ window = gtk_dialog_new (); gtk_signal_connect (GTK_OBJECT (window), \"destroy\", (GtkSignalFunc) destroy, NULL); gtk_window_set_title (GTK_WINDOW (window), \"dialog\"); gtk_container_border_width (GTK_CONTAINER (window), 0);
/* create a new scrolled window. */ scrolled_window = gtk_scrolled_window_new (NULL, NULL);
/* the policy is one of GTK_POLICY AUTOMATIC, or GTK_POLICY_ALWAYS. * GTK_POLICY_AUTOMATIC will automatically decide whether you need * scrollbars, wheras GTK_POLICY_ALWAYS will always leave the scrollbars * there. The first one is the horizontal scrollbar, the second, * the vertical. */ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); /* The dialog window is created with a vbox packed into it. */ gtk_box_pack_start (GTK_BOX (GTK_DIALOG(window)->vbox), scrolled_window, TRUE, TRUE, 0); gtk_widget_show (scrolled_window);
/* create a table of 10 by 10 squares. */ table = gtk_table_new (10, 10, FALSE);
/* set the spacing to 10 on x and 10 on y */ gtk_table_set_row_spacings (GTK_TABLE (table), 10); gtk_table_set_col_spacings (GTK_TABLE (table), 10);
/* pack the table into the scrolled window */ gtk_container_add (GTK_CONTAINER (scrolled_window), table); gtk_widget_show (table);
/* this simply creates a grid of toggle buttons on the table * to demonstrate the scrolled window. */ for (i = 0; i < 10; i++) for (j = 0; j < 10; j++) { sprintf (buffer, \"button (%d,%d)\\n\", i, j); button = gtk_toggle_button_new_with_label (buffer); gtk_table_attach_defaults (GTK_TABLE (table), button, i, i+1, j, j+1); gtk_widget_show (button); }
/* Add a \"close\" button to the bottom of the dialog */ button = gtk_button_new_with_label (\"close\"); gtk_signal_connect_object (GTK_OBJECT (button), \"clicked\", (GtkSignalFunc) gtk_widget_destroy, GTK_OBJECT (window));
/* This grabs this button to be the default button. Simply hitting * the \"Enter\" key will cause this button to activate. */ gtk_widget_grab_default (button); gtk_widget_show (button);
label = gtk_label_new (\"Click here to quit, quit, quit, quit, quit\"); gtk_container_add (GTK_CONTAINER (event_box), label); gtk_widget_show (label);
/* 把它裁短 */ gtk_widget_set_usize (label, 110, 20);
/* And bind an action to it */ gtk_widget_set_events (event_box, GDK_BUTTON_PRESS_MASK); gtk_signal_connect (GTK_OBJECT(event_box), \"button_press_event\", GTK_SIGNAL_FUNC (gtk_exit), NULL);
Progress Bars一般与timeouts及其它函数一起使用, (see section on Timeouts, I/O and Idle Functions) 这是因为多工的考量. gtk_progress_bar_update会处理这方面的事务.
这里是使用Progress Bar的范例, 并用timeouts来更新. 同时也会展示如何重设Progress Bar.
#include
static int ptimer = 0; int pstat = TRUE;
/* This function increments and updates the progress bar, it also resets the progress bar if pstat is FALSE */ gint progress (gpointer data) { gfloat pvalue;
/* get the current value of the progress bar */ pvalue = GTK_PROGRESS_BAR (data)->percentage;
label = gtk_label_new (\"Progress Bar Example\"); gtk_table_attach_defaults(GTK_TABLE(table), label, 0,2,0,1); gtk_widget_show(label);
/* Create a new progress bar, pack it into the table, and show it */ pbar = gtk_progress_bar_new (); gtk_table_attach_defaults(GTK_TABLE(table), pbar, 0,2,1,2); gtk_widget_show (pbar);
/* Set the timeout to handle automatic updating of the progress bar */ ptimer = gtk_timeout_add (100, progress, pbar);
/* This button signals the progress bar to be reset */ button = gtk_button_new_with_label (\"Reset\"); gtk_signal_connect (GTK_OBJECT (button), \"clicked\", GTK_SIGNAL_FUNC (progress_r), NULL); gtk_table_attach_defaults(GTK_TABLE(table), button, 0,1,2,3); gtk_widget_show(button);
/* compile this program with: * $ gcc -I/usr/local/include/ -lgtk -lgdk -lglib -lX11 -lm -Wall main.c */
/* include the gtk+ header files * include stdio.h, we need that for the printf() function */ #include #include
/* this is our data identification string to store * data in list items */ const gchar *list_item_data_key=\"list_item_data\";
/* prototypes for signal handler that we are going to connect * to the GtkList widget */ static void sigh_print_selection (GtkWidget *gtklist, gpointer func_data); static void sigh_button_event (GtkWidget *gtklist, GdkEventButton *event, GtkWidget *frame);
/* create a window to put all the widgets in * connect gtk_main_quit() to the \"destroy\" event of * the window to handle window manager close-window-events */ window=gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window), \"GtkList Example\"); gtk_signal_connect(GTK_OBJECT(window), \"destroy\", GTK_SIGNAL_FUNC(gtk_main_quit), NULL);
/* inside the window we need a box to arrange the widgets * vertically */ vbox=gtk_vbox_new(FALSE, 5); gtk_container_border_width(GTK_CONTAINER(vbox), 5); gtk_container_add(GTK_CONTAINER(window), vbox); gtk_widget_show(vbox);
/* this is the scolled window to put the GtkList widget inside */ scrolled_window=gtk_scrolled_window_new(NULL, NULL); gtk_widget_set_usize(scrolled_window, 250, 150); gtk_container_add(GTK_CONTAINER(vbox), scrolled_window); gtk_widget_show(scrolled_window);
/* create the GtkList widget * connect the sigh_print_selection() signal handler * function to the \"selection_changed\" signal of the GtkList * to print out the selected items each time the selection * has changed */ gtklist=gtk_list_new(); gtk_container_add(GTK_CONTAINER(scrolled_window), gtklist); gtk_widget_show(gtklist); gtk_signal_connect(GTK_OBJECT(gtklist), \"selection_changed\", GTK_SIGNAL_FUNC(sigh_print_selection), NULL);
/* we create a \"Prison\" to put a list item in ;) */ frame=gtk_frame_new(\"Prison\"); gtk_widget_set_usize(frame, 200, 50); gtk_container_border_width(GTK_CONTAINER(frame), 5); gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT); gtk_container_add(GTK_CONTAINER(vbox), frame); gtk_widget_show(frame);
/* connect the sigh_button_event() signal handler to the GtkList * wich will handle the \"arresting\" of list items */ gtk_signal_connect(GTK_OBJECT(gtklist), \"button_release_event\", GTK_SIGNAL_FUNC(sigh_button_event), frame);
/* create a separator */ separator=gtk_hseparator_new(); gtk_container_add(GTK_CONTAINER(vbox), separator); gtk_widget_show(separator);
/* finaly create a button and connect it愀 \"clicked\" signal * to the destroyment of the window */ button=gtk_button_new_with_label(\"Close\"); gtk_container_add(GTK_CONTAINER(vbox), button); gtk_widget_show(button); gtk_signal_connect_object(GTK_OBJECT(button), \"clicked\", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(window));
/* now we create 5 list items, each having it愀 own * label and add them to the GtkList using gtk_container_add() * also we query the text string from the label and * associate it with the list_item_data_key for each list item */ for (i=0; i<5; i++) { GtkWidget *label; gchar *string;
sprintf(buffer, \"ListItemContainer with Label #%d\", i); label=gtk_label_new(buffer); list_item=gtk_list_item_new(); gtk_container_add(GTK_CONTAINER(list_item), label); gtk_widget_show(label); gtk_container_add(GTK_CONTAINER(gtklist), list_item); gtk_widget_show(list_item); gtk_label_get(GTK_LABEL(label), &string); gtk_object_set_data(GTK_OBJECT(list_item), list_item_data_key, string); } /* here, we are creating another 5 labels, this time * we use gtk_list_item_new_with_label() for the creation * we can憩 query the text string from the label because * we don憩 have the labels pointer and therefore * we just associate the list_item_data_key of each * list item with the same text string * for adding of the list items we put them all into a doubly * linked list (GList), and then add them by a single call to * gtk_list_append_items() * because we use g_list_prepend() to put the items into the * doubly linked list, their order will be descending (instead * of ascending when using g_list_append()) */ dlist=NULL; for (; i<10; i++) { sprintf(buffer, \"List Item with Label %d\", i); list_item=gtk_list_item_new_with_label(buffer); dlist=g_list_prepend(dlist, list_item); gtk_widget_show(list_item); gtk_object_set_data(GTK_OBJECT(list_item), list_item_data_key, \"ListItem with integrated Label\"); } gtk_list_append_items(GTK_LIST(gtklist), dlist);
/* finaly we want to see the window, don憩 we? ;) */ gtk_widget_show(window);
/* fire up the main event loop of gtk */ gtk_main();
/* we get here after gtk_main_quit() has been called which * happens if the main window gets destroyed */ return 0; }
/* this is the signal handler that got connected to button * press/release events of the GtkList */ void sigh_button_event (GtkWidget *gtklist, GdkEventButton *event, GtkWidget *frame) { /* we only do something if the third (rightmost mouse button * was released */ if (event->type==GDK_BUTTON_RELEASE && event->button==3) { GList *dlist, *free_list; GtkWidget *new_prisoner;
/* fetch the currently selected list item which * will be our next prisoner ;) */ dlist=GTK_LIST(gtklist)->selection; if (dlist) new_prisoner=GTK_WIDGET(dlist->data); else new_prisoner=NULL;
/* look for already prisoned list items, we * will put them back into the list * remember to free the doubly linked list that * gtk_container_children() returns */ dlist=gtk_container_children(GTK_CONTAINER(frame)); free_list=dlist; while (dlist) { GtkWidget *list_item;
list_item=dlist->data;
gtk_widget_reparent(list_item, gtklist);
dlist=dlist->next; } g_list_free(free_list);
/* if we have a new prisoner, remove him from the * GtkList and put him into the frame \"Prison\" * we need to unselect the item before */ if (new_prisoner) { GList static_dlist;
/* this is the signal handler that gets called if GtkList * emits the \"selection_changed\" signal */ void sigh_print_selection (GtkWidget *gtklist, gpointer func_data) { GList *dlist;
/* fetch the doubly linked list of selected items * of the GtkList, remember to treat this as read-only! */ dlist=GTK_LIST(gtklist)->selection;
/* if there are no selected items there is nothing more * to do than just telling the user so */ if (!dlist) { g_print(\"Selection cleared\\n\"); return; } /* ok, we got a selection and so we print it */ g_print(\"The selection is a \");
/* get the list item from the doubly linked list * and then query the data associated with list_item_data_key * we then just print it */ while (dlist) { GtkObject *list_item; gchar *item_data_string;
传一个generic pointer到`GtkListItemClass*\". *Note Standard Macros::, for more info.
gint GTK_IS_LIST_ITEM (gpointer OBJ)
决定generic pointer是否对照到`GtkListItem\" object. *Note Standard Macros::, for more info.
12.7 例子 Please see the GtkList example on this, which covers the usage of a GtkListItem as well.
-------------------------------------------------------------------------------- 译注: List物件这一篇本身比较不容易翻译, 因原文本身讲的并不太清楚. 此外, 其结构原本就比较繁琐. 若您在此糟遇问题, 可来信反应. 译者会想办法将其改善. If you got stuck here, it\"s mostly not your problem. Don\"t feel frustration. The List Widget itself is pretty complicated. You may drop me a word if you need. I will try to improve it.
/* create a new window */ window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW (window), \"GTK Menu Test\"); gtk_signal_connect(GTK_OBJECT (window), \"destroy\", (GtkSignalFunc) gtk_exit, NULL);
/* Init the menu-widget, and remember -- never * gtk_show_widget() the menu widget!! */ menu = gtk_menu_new();
/* This is the root menu, and will be the label will be the menu name displayed on * the menu bar. There won\"t be * a signal handler attached, as it only pops up the rest of the menu when pressed. */ root_menu = gtk_menu_item_new_with_label(\"Root Menu\");
gtk_widget_show(root_menu);
/* Next we make a little loop that makes three menu-entries for \"test-menu\". * Notice the call to gtk_menu_append. Here we are adding a list of menu items * to our menu. Normally, we\"d also catch the \"clicked\" signal on each of the * menu items and setup a callback for it, but it\"s omitted here to save space. */
for(i = 0; i < 3; i++) { /* Copy the names to the buf. */ sprintf(buf, \"Test-undermenu - %d\", i);
/* Create a new menu-item with a name... */ menu_items = gtk_menu_item_new_with_label(buf);
/* ...and add it to the menu. */ gtk_menu_append(GTK_MENU (menu), menu_items);
/* Show the widget */ gtk_widget_show(menu_items); }
/* Now we specify that we want our newly created \"menu\" to be the menu for the \"root menu\" */ gtk_menu_item_set_submenu(GTK_MENU_ITEM (root_menu), menu);
/* Create a menu-bar to hold the menus and add it to our main window*/ menu_bar = gtk_menu_bar_new(); gtk_container_add(GTK_CONTAINER(window), menu_bar); gtk_widget_show(menu_bar);
/* And finally we append the menu-item to the menu-bar -- this is the \"root\" * menu-item I have been raving about =) */ gtk_menu_bar_append(GTK_MENU_BAR (menu_bar), root_menu);
/* always display the window as the last step so it all splashes on the screen at once. */ gtk_widget_show(window);
/* this is the GtkMenuEntry structure used to create new menus. The * first member is the menu definition string. The second, the * default accelerator key used to access this menu function with * the keyboard. The third is the callback function to call when * this menu item is selected (by the accelerator key, or with the * mouse.) The last member is the data to pass to your callback function. */
void menus_set_sensitive(char *path, int sensitive) { GtkMenuPath *menu_path;
if (initialize) menus_init();
menu_path = gtk_menu_factory_find(factory, path); if (menu_path) gtk_widget_set_sensitive(menu_path->widget, sensitive); else g_warning(\"Unable to set sensitivity for menu which doesn\"t exist: %s\", path); }
/* This is just to demonstrate how callbacks work when using the * menufactory. Often, people put all the callbacks from the menus * in a separate file, and then have them call the appropriate functions * from there. Keeps it more organized. */ void file_quit_cmd_callback (GtkWidget *widget, gpointer data) { g_print (\"%s\\n\", (char *) data); gtk_exit(0); }
/* Signal handler invoked when user clicks on the \"Get Targets\" button */ void get_targets (GtkWidget *widget, gpointer data) { static GdkAtom targets_atom = GDK_NONE;
/* Get the atom corresonding to the string \"TARGETS\" */ if (targets_atom == GDK_NONE) targets_atom = gdk_atom_intern (\"TARGETS\", FALSE);
/* And request the \"TARGETS\" target for the primary selection */ gtk_selection_convert (widget, GDK_SELECTION_PRIMARY, targets_atom, GDK_CURRENT_TIME); }
/* Signal handler called when the selections owner returns the data */ void selection_received (GtkWidget *widget, GtkSelectionData *selection_data, gpointer data) { GdkAtom *atoms; GList *item_list; int i;
/* **** IMPORTANT **** Check to see if retrieval succeeded */ if (selection_data->length < 0) { g_print (\"Selection retrieval failed\\n\"); return; } /* Make sure we got the data in the expected form */ if (selection_data->type != GDK_SELECTION_TYPE_ATOM) { g_print (\"Selection \\\"TARGETS\\\" was not returned as atoms!\\n\"); return; }
/* Print out the atoms we received */ atoms = (GdkAtom *)selection_data->data;
item_list = NULL; for (i=0; ilength/sizeof(GdkAtom); i++) { char *name; name = gdk_atom_name (atoms[i]); if (name != NULL) g_print (\"%s\\n\",name); else g_print (\"(bad atom)\\n\"); }
return; }
int main (int argc, char *argv[]) { GtkWidget *window; GtkWidget *button;
/* Callback when the user toggles the selection */ void selection_toggled (GtkWidget *widget, gint *have_selection) { if (GTK_TOGGLE_BUTTON(widget)->active) { *have_selection = gtk_selection_owner_set (widget, GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME); /* if claiming the selection failed, we return the button to the out state */ if (!*have_selection) gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON(widget), FALSE); } else { if (*have_selection) { /* Before clearing the selection by setting the owner to NULL, we check if we are the actual owner */ if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == widget->window) gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME); *have_selection = FALSE; } } }
/* Called when another application claims the selection */ gint selection_clear (GtkWidget *widget, GdkEventSelection *event, gint *have_selection) { *have_selection = FALSE; gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON(widget), FALSE);
return TRUE; }
/* Supplies the current time as the selection. */ void selection_handle (GtkWidget *widget, GtkSelectionData *selection_data, gpointer data) { gchar *timestr; time_t current_time;
current_time = time (NULL); timestr = asctime (localtime(¤t_time)); /* When we return a single string, it should not be null terminated. That will be done for us */
# Here is a list of all the possible states. Note that some do not apply to # certain widgets. # # NORMAL - The normal state of a widget, without the mouse over top of # it, and not being pressed etc. # # PRELIGHT - When the mouse is over top of the widget, colors defined # using this state will be in effect. # # ACTIVE - When the widget is pressed or clicked it will be active, and # the attributes assigned by this tag will be in effect. # # INSENSITIVE - When a widget is set insensitive, and cannot be # activated, it will take these attributes. # # SELECTED - When an object is selected, it takes these attributes. # # Given these states, we can set the attributes of the widgets in each of # these states using the following directives. # # fg - Sets the foreground color of a widget. # fg - Sets the background color of a widget. # bg_pixmap - Sets the background of a widget to a tiled pixmap. # font - Sets the font to be used with the given widget. #
# This sets a style called \"button\". The name is not really important, as # it is assigned to the actual widgets at the bottom of the file.
style \"window\" { #This sets the padding around the window to the pixmap specified. #bg_pixmap[] = \" \" bg_pixmap[NORMAL] = \"warning.xpm\" }
style \"scale\" { #Sets the foreground color (font color) to red when in the \"NORMAL\" #state.
fg[NORMAL] = { 1.0, 0, 0 }
#Sets the background pixmap of this widget to that of it\s parent. bg_pixmap[NORMAL] = \" \" }
style \"button\" { # This shows all the possible states for a button. The only one that # doesn\t apply is the SELECTED state.
# In this example, we inherit the attributes of the \"button\" style and then # override the font and background color when prelit to create a new # \"main_button\" style.
style \"ruler\" { font = \"-adobe-helvetica-medium-r-normal--*-80-*-*-*-*-*-*\" }
# pixmap_path \"~/.pixmaps\"
# These set the widget types to use the styles defined above. # The widget types are listed in the class hierarchy, but could probably be # just listed in this document for the users reference.
# This sets all the buttons that are children of the \"main window\" to # the main_buton style. These must be documented to be taken advantage of. widget \"main window.*GtkButton*\" style \"main_button\"
/* Create a new Tictactoe widget */ ttt = tictactoe_new (); gtk_container_add (GTK_CONTAINER (window), ttt); gtk_widget_show (ttt);
/* And attach to its \"tictactoe\" signal */ gtk_signal_connect (GTK_OBJECT (ttt), \"tictactoe\", GTK_SIGNAL_FUNC (win), NULL);
gtk_widget_show (window);
gtk_main ();
return 0; }
20.4 从草稿中产生物件.
基本 我们的物件看起来会有点像Tictactoe物件.
/* GTK - The GIMP Toolkit * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Determine if button press was within pointer region - we do this by computing the parallel and perpendicular distance of the point where the mouse was pressed from the line passing through the pointer */
20.6 版权 This section on of the tutorial on writing widgets is Copyright (C) 1997 Owen Taylor
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.