📄 gtk_tut_it.txt
字号:
gtk_signal_handlers_destroy (GtkObject *object); Questa chiamata e abbastanza auto esplicativa. Semplicemente rimuove tutti i segnali collegati al widget che si passa alla funzione come argomento. 33..33.. MMiigglliioorriiaammoo HHeelllloo WWoorrlldd Diamo un'occhiata ad una versione migliorata di Hello World con altri esempi sulle callback. Questo ci introdurra anche al nostro prossimo argomento, l'impacchettamento dei widget. /* helloworld2.c */ #include <gtk/gtk.h> /* La nostra funzione di callback migliorata. I dati passati a questa * vengono stampati su stdout. */ void callback (GtkWidget *widget, gpointer data) { g_print ("Hello again - %s was pressed\n", (char *) data); } /* Un'altra callback */ void delete_event (GtkWidget *widget, gpointer data) { gtk_main_quit (); } int main (int argc, char *argv[]) { /* GtkWidget e' il tipo di dato per i widget */ GtkWidget *window; GtkWidget *button; GtkWidget *box1; /* Questa funzione e' invocata in tutte le applicazioni GTK, gli argomenti sono analizzati e restituiti all'applicazione. */ gtk_init (&argc, &argv); /* Crea una nuova finestra */ window = gtk_window_new (GTK_WINDOW_TOPLEVEL); /* Questa e' una nuova chiamata. Assegna "Hello Buttons" come titolo della nostra finestra */ gtk_window_set_title (GTK_WINDOW (window), "Hello Buttons!"); /* Qui settiamo il gestore per il segnale "delete_event" che immediatamente esce dalla applicazione. gtk_signal_connect (GTK_OBJECT (window), "delete_event", GTK_SIGNAL_FUNC (delete_event), NULL); /* predispone il bordo della finestra */ gtk_container_border_width (GTK_CONTAINER (window), 10); /* creiamo una scatola dove mettere tutti i widget. Questa e descritta dettagliatamente nella sezione "packing". La scatola non e realmente visibile, e solamente usata per sistemare i widget. */ box1 = gtk_hbox_new(FALSE, 0); /* Inseriamo la scatola nella finestra */ gtk_container_add (GTK_CONTAINER (window), box1); /* Creiamo un nuovo bottone con etichetta "Button 1" */ button = gtk_button_new_with_label ("Button 1"); /* Quando il bottone e' premuto, noi invocheremo la funzione di callback, con un puntatore alla stringa "button 1" come proprio argomento) */ gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (callback), (gpointer) "button 1"); /* invece di aggiungerlo alla finestra, lo inseriamo nella scatola invisibile, la quale e' stata inserita nella finstra. */ gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0); /* Ricordati sempre questo passo. Dice a GTK che la preparazione di questo bottone e' finita e che quindi puo' essere mostrato. */ gtk_widget_show(button); /* Facciamo la stessa cosa per il secondo bottone. */ button = gtk_button_new_with_label ("Button 2"); /* Chiamiamo la stessa funzione ma passandogli un argomento differente, gli passiamo un puntatore alla stringa "button 2" */ 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); /* L'ordine nel quale i bottoni sono visualizzati non e' realmente importante, ma io ti raccomando di mostrare per ultima la finestra cosi' che tutto sia visualizzato in una volta sola */ gtk_widget_show(button); gtk_widget_show(box1); gtk_widget_show (window); /* e ora ci mettiamo in gtk_main e aspettiamo che il diverimento inizi. gtk_main (); return 0; } Compilate questo programma usando gli stessi argomenti di link del nostro primo esempio. Noterete che questa volta non c'e un modo semplice per uscire dal programma, si deve usare il nostro window manager o la linea di comando per uccidere l'applicazione. Un buon esercizio per il lettore e quello di inserire un tezo bottone ``quit'' che faccia uscire dal programma. Potete anche divertirvi con le opzioni di gtk_box_pack_start() mentre leggete il prossimo capitolo. Provate a ridimensionare la finestra ed a osservare cosa succede. Solo una piccola nota: c'e un'altra definizione di gtk_window_new() - GTK_WINDOW_DIALOG. Questa interagisce con il window manager in un modo un po' diverso, e dovrebbe essere usata per finestre temporanee. 44.. CCoommee ````IImmppaacccchheettttaarree'''' ii WWiiddggeett Nel momento in cui si crea un'applicazione, normalmente si avra la necessita di mettere piu di un unico bottone all'interno di una finestra. Il nostro primo esempio ``Hello World'' usava un solo oggetto, cosicche abbiamo potuto usare semplicemente una chiamata a gtk_container_add per impacchettare il widget nella finestra. Quando invece si vuole inserire piu di un unico widget in una finestra, come si fa a controllare dove vengono posizionati i propri oggetti? E' qui che entra in gioco il meccanismo dell'``impacchettamento''. 44..11.. TTeeoorriiaa ddeellllee SSccaattoollee ppeerr IImmppaacccchheettttaammeennttoo La maggior parte dell'impacchettamento viene effettuata creando delle scatole come nell'esempio piu sopra. Le scatole sono dei contenitori invisibili di widget che possiamo usare per imballarci i nostri oggetti e che esistono in due varieta: in particolare si possono avere scatole orizzontali (hbox) e verticali (vbox). Quando si impacchentano degli oggetti in una scatola orizzontale, gli oggetti vengono inseriti orizzontalmente da sinistra a destra oppure da destra a sinistra a seconda della chiamata di funzione che si usa. In una scatola verticale, gli oggetti vengono inseriti dall'alto in basso o viceversa. Si puo usare qualsiasi combinazione di scatole all'interno o a fianco di altre scatole, fino ad ottenere l'effetto desiderato. Per creare una nuova scatola orizzontale, si usa una chiamata a gtk_hbox_new(), mentre per le scatole verticali si usa gtk_vbox_new(). Per inserire i widget all'interno di questi contenitori si usano le funzioni gtk_box_pack_start() e gtk_box_pack_end(). La funzione gtk_box_pack_start() comincera dall'alto verso il basso in una vbox e da sinistra a destra in una hbox. gtk_box_pack_end() fa l'opposto, impacchettando dal basso verso l'alto in una vbox e da destra a sinistra in una hbox. Queste funzioni ci permettono di giustificare a destra o a sinistra i nostri widget, e possono essere mescolate in qualsiasi modo per ottenere l'effetto desiderato. Useremo gtk_box_pack_start() nella maggior parte dei nostri esempi. Un oggetto puo essere costituito da un altro contenitore o da un oggetto grafico. Infatti, molti oggetti grafici sono a loro volta dei contenitori, compreso il bottone, anche se tipicamente all'interno del bottone mettiamo solo una etichetta. Usando queste chiamate, GTK riesce a capire dove si vogliono piazzare i propri widget, in modo di essere poi in grado di effettuare il ridimensionamento automatico e altre cose interessanti. Esiste poi un insieme di opzioni che riguardano il modo in cui i propri oggetti grafici dovrebbero essere impacchettati. Come si puo immaginare, questo metodo da una buona flessibilita nella creazione e nella disposizione dei propri widget. 44..22.. DDeettttaaggllii ssuullllee SSccaattoollee A causa di questa flessibilita, le scatole per impacchettamento del GTK possono, di primo acchito, creare un po' di disorientamento. Sono infatti disponibili molte opzioni, e non e immediato il modo in cui si combinano l'una con l'altra. Alla fine pero, si possono ottenere essenzialmente cinque diversi stili. <CENTER > <IMG SRC="gtk_tut_packbox1.gif" VSPACE="15" HSPACE="10" WIDTH="528" HEIGHT="235" ALT="Box Packing Example Image" > </CENTER > Ogni linea contiene una scatola orizzontale (hbox) con diversi bottoni. La chiamata a gtk_box_pack e una scorciatoia per la chiamata di impacchettamento di ognuno dei bottoni nella hbox. Ognuno dei bottoni viene impacchettato nella hbox nello stesso modo (cioe, con gli stessi argomenti per la funzione gtk_box_pack_start ()). Questa e la dichiarazione della funzione gtk_box_pack_start. void gtk_box_pack_start (GtkBox *box, GtkWidget *child, gint expand, gint fill, gint padding); Il primo argomento e la scatola nella quale si stanno inscatolando i widget, il secondo e il widget stesso. Gli oggetti per ora saranno bottoni, quindi quello che faremo sara impacchettare bottoni in sca- tole. L'argomento ``expand'' in gtk_box_pack_start() o gtk_box_pack_end() controlla se gli oggetti devono essere sistemati nella scatola in modo da riempire tutto lo spazio in diponibile presente nella scatola, in modo che la scatola si espanda fino ad occupare tutta l'area assegnatale (valore TRUE). La scatola puo anche essere rimpiciolita in modo da contenere esattamente i widget (valore FALSE). Assegnare a expand il valore FALSE permette di giustificare a destra o sinistra i propri oggetti. In caso contrario, tutti gli ogetti si espandono fino ad adattarsi alla scatola, e il medesimo effetto si puo ottenere usando solo una delle funzioni gtk_box_pack_start o pack_end. L'argomento ``fill'' delle funzioni gtk_box_pack stabilisce se lo spazio disponibile nella scatola deve essere allocato agli oggetti (TRUE) o se deve essere mantenuto come riempimento attorno a questi oggetti (FALSE). Questo argomento ha effetto solo se a expand e assegnato il valore TRUE. Quando si crea una nuova scatola, la funzione ha questo aspetto: GtkWidget * gtk_hbox_new (gint homogeneous, gint spacing); L'argomento homogeneous di gtk_hbox_new (la stesso per gtk_vbox_new) determina se ogni oggetto nella scatola deve avere la stessa dimensione (cioe la stessa ampiezza in una hbox o la stessa altezza in una vbox). Se e settato, l'argomento expand delle routine gtk_box_pack e sempre attivato. Qual e la differenza fra la spaziatura (che e stabilita quando la scatola viene creata) e il riempimento (che viene stabilito quando gli elementi vengono impacchettati)? La spaziatura viene inserita fra gli oggetti, mentre il riempimento viene aggiuno a ciascuno dei lati dell'oggetti. La seguente figura dovrebbe chiarire meglio questo punto: <CENTER > <IMG ALIGN="center" SRC="gtk_tut_packbox2.gif" WIDTH="509" HEIGHT="213" VSPACE="15" HSPACE="10" ALT="Box Packing Example Image" > </CENTER > Di seguito e riportato il codice usato per creare le immagini precedenti. L'ho commentato in modo piuttosto pesante, in modo che non dovreste avere problemi nel seguirlo. Compilatelo voi stessi e provate a giocarci un po'. 44..33.. PPrrooggrraammmmaa DDiimmoossttrraattiivvoo ddii IImmppaacccchheettttaammeennttoo /* packbox.c */ #include "gtk/gtk.h" void delete_event (GtkWidget *widget, gpointer data) { gtk_main_quit (); } /* Costruisco una nuova hbox riempita con bottoni-etichette. Gli * argomenti per le varabili che ci interessano sono passati * in questa funzione. Non mostriamo la scatola, ma mostriamo * tutto quello che c'e' dentro. */ GtkWidget *make_box (gint homogeneous, gint spacing, gint expand, gint fill, gint padding) { GtkWidget *box; GtkWidget *button; char padstr[80]; /* costruisco una nuova hbox con i valori appropriati di * homogeneous e spacing */ box = gtk_hbox_new (homogeneous, spacing); /* costruisco una serie di bottoni con i valori appropriati */ button = gtk_button_new_with_label ("gtk_box_pack"); gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding); gtk_widget_show (button); button = gtk_button_new_with_label ("(box,"); gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding); gtk_widget_show (button); button = gtk_button_new_with_label ("button,"); gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding); gtk_widget_show (button); /* costruisco un bottone con l'etichetta che dipende dal valore di * expand. */ if (expand == TRUE) button = gtk_button_new_with_label ("TRUE,"); else button = gtk_button_new_with_label ("FALSE,"); gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding); gtk_widget_show (button); /* Questo e' la stessa cosa della creazione del bottone per "expand" * piu' sopra, ma usa la forma breve. */ button = gtk_button_new_with_label (fill ? "TRUE," : "FALSE,"); gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding); gtk_widget_show (button); sprintf (padstr, "%d);", padding); button = gtk_button_new_with_label (padstr); gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding); gtk_widget_show (button); return box; } int main (int argc, char *argv[]) { GtkWidget *window; GtkWidget *button; GtkWidget *box1; GtkWidget *box2; GtkWidget *separator; GtkWidget *label; GtkWidget *quitbox; int which; /* La nostra inizializzazione, non dimenticatela! :) */ gtk_init (&argc, &argv); if (argc != 2) { fprintf (stderr, "uso: packbox num, dove num e 1, 2, o 3.\n"); /* questo fa solo un po' di pulizia in GTK, ed esce con un valore 1. */ gtk_exit (1); } which = atoi (argv[1]); /* Creiamo la nostra finestra */ window = gtk_window_new (GTK_WINDOW_TOPLEVEL); /* Ci si dovrebbe sempre ricordare di connettere il segnale di destroy * alla finestra principale. Cio' e' molto importante per avere un funzionamento * corretto dal punto di vista intuitivo */ gtk_signal_connect (GTK_OBJECT (window), "delete_event", GTK_SIGNAL_FUNC (delete_event), NULL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -