File: gtk_tut_it-4.html

package info (click to toggle)
gtk%2B1.2 1.2.10-18
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 14,468 kB
  • ctags: 12,966
  • sloc: ansic: 137,190; sh: 13,303; makefile: 1,170; perl: 328; awk: 274; lisp: 7
file content (683 lines) | stat: -rw-r--r-- 28,862 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<HTML>
<HEAD>
 <META NAME="GENERATOR" CONTENT="SGML-Tools 1.0.9">
 <TITLE>GTK Tutorial: Come ``Impacchettare'' i Widget </TITLE>
 <LINK HREF="gtk_tut_it-5.html" REL=next>
 <LINK HREF="gtk_tut_it-3.html" REL=previous>
 <LINK HREF="gtk_tut_it.html#toc4" REL=contents>
</HEAD>
<BODY BGCOLOR="#FFFFFF">
<A HREF="gtk_tut_it-5.html">Avanti</A>
<A HREF="gtk_tut_it-3.html">Indietro</A>
<A HREF="gtk_tut_it.html#toc4">Indice</A>
<HR NOSHADE>
<H2><A NAME="s4">4. Come ``Impacchettare'' i Widget </A></H2>

<P>Nel momento in cui si crea un'applicazione, normalmente si avr&agrave; la
necessit&agrave; di mettere pi&ugrave; di un unico bottone all'interno di
una finestra. Il nostro primo esempio ``Hello World'' usava un solo oggetto,
cosicch&eacute; abbiamo potuto usare semplicemente una chiamata a
gtk_container_add per impacchettare il widget nella finestra. Quando invece
si vuole inserire pi&ugrave; 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''.
<H2><A NAME="ss4.1">4.1 Teoria delle Scatole per Impacchettamento</A>
</H2>

<P>La maggior parte dell'impacchettamento viene effettuata creando delle scatole
come nell'esempio pi&ugrave; sopra. Le scatole sono dei contenitori invisibili
di widget che possiamo usare per imballarci i nostri oggetti e che esistono in
due variet&agrave;: 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 pu&ograve; usare
qualsiasi combinazione di scatole all'interno o a fianco di altre scatole, fino
ad ottenere l'effetto desiderato.
<P>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() comincer&agrave; 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 pu&ograve; 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.
<P>
<P>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 pu&ograve; immaginare, questo metodo d&agrave; una buona flessibilit&agrave; nella creazione e
nella disposizione dei propri widget.
<P>
<H2><A NAME="ss4.2">4.2 Dettagli sulle Scatole</A>
</H2>

<P>A causa di questa flessibilit&agrave;, le scatole per impacchettamento del GTK
possono, di primo acchito, creare un po' di disorientamento. Sono infatti disponibili
molte opzioni, e non &egrave; immediato il modo in cui si combinano l'una con l'altra.
Alla fine per&ograve;, si possono ottenere essenzialmente cinque diversi stili.
<P>
<P> <CENTER >
<IMG SRC="gtk_tut_packbox1.gif" VSPACE="15" HSPACE="10" WIDTH="528" HEIGHT="235"
ALT="Box Packing Example Image"
> </CENTER
 >
<P>Ogni linea contiene una scatola orizzontale (hbox) con diversi bottoni. 
La chiamata a  gtk_box_pack &egrave; una scorciatoia per la chiamata di
impacchettamento di ognuno dei bottoni nella hbox. Ognuno dei bottoni viene
impacchettato nella hbox nello stesso modo (cio&egrave;, con gli stessi
argomenti per la funzione gtk_box_pack_start ()).
<P>Questa &egrave; la dichiarazione della funzione gtk_box_pack_start.
<P>
<BLOCKQUOTE><CODE>
<PRE>
void gtk_box_pack_start (GtkBox    *box,
                         GtkWidget *child,
                         gint       expand,
                         gint       fill,
                         gint       padding);
</PRE>
</CODE></BLOCKQUOTE>

Il primo argomento &egrave; la scatola nella quale si stanno inscatolando i
widget, il secondo &egrave; il widget stesso. Gli oggetti per ora saranno 
bottoni, quindi quello che faremo sar&agrave; impacchettare bottoni in scatole.
<P>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 pu&ograve; 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 pu&ograve;
ottenere usando solo una delle funzioni gtk_box_pack_start o pack_end.
<P>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 &egrave; assegnato il valore TRUE.
<P>Quando si crea una nuova scatola, la funzione ha questo aspetto:
<P>
<BLOCKQUOTE><CODE>
<PRE>
GtkWidget * gtk_hbox_new (gint homogeneous,
                          gint spacing);
</PRE>
</CODE></BLOCKQUOTE>
<P>L'argomento homogeneous di gtk_hbox_new (la stesso per gtk_vbox_new)
determina se ogni oggetto nella scatola deve avere la stessa dimensione
(cio&egrave; la stessa ampiezza in una hbox o la stessa altezza in una vbox).
Se &egrave; settato, l'argomento expand delle routine gtk_box_pack &egrave;
sempre attivato.
<P>Qual &egrave; la differenza fra la spaziatura (che &egrave; 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:
<P> <CENTER >
<IMG ALIGN="center" SRC="gtk_tut_packbox2.gif" WIDTH="509" HEIGHT="213"
VSPACE="15" HSPACE="10" ALT="Box Packing Example Image"
> </CENTER
 >
<P>
<P>Di seguito &egrave; 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'.
<P>
<H2><A NAME="ss4.3">4.3 Programma Dimostrativo di Impacchettamento</A>
</H2>

<P>
<P>
<BLOCKQUOTE><CODE>
<PRE>
/* 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 (&amp;argc, &amp;argv);
    
    if (argc != 2) {
        fprintf (stderr, "uso: packbox num, dove num &egrave; 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);
    gtk_container_border_width (GTK_CONTAINER (window), 10);
    
    /* Creiamo una scatola verticale (vbox) in cui impacchettare quelle
     * orizzontali. Questo ci permette di impilare le scatole orizzontali
     * piene di bottoni una sull'altra in questa vbox. */
  
    box1 = gtk_vbox_new (FALSE, 0);
    
    /* Decide quale esempio si deve mostrare. Corrispondono alle figure precedenti */
    switch (which) {
    case 1:
        /* creare una nuova etichetta. */
        label = gtk_label_new ("gtk_hbox_new (FALSE, 0);");
        
        /* allineare l'etichetta al lato sinistro. Discuteremo questa e altre
         * funzioni nella sezione dedicata agli attributi degli oggetti grafici. */
        gtk_misc_set_alignment (GTK_MISC (label), 0, 0);

        /* Impacchettare l'etichetta nella scatola verticale (vbox box1).
         * Ricordare che gli oggetti che vengono aggiunti in una vbox vengono
         * impacchettati uno sopra all'altro in ordine. */
        gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
        
        /* mostrare l'etichetta */
        gtk_widget_show (label);
        
        /* chiamare la nostra funzione make_box - homogeneous = FALSE,
         * spacing = 0, expand = FALSE, fill = FALSE, padding = 0 */
        box2 = make_box (FALSE, 0, FALSE, FALSE, 0);
        gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
        gtk_widget_show (box2);

        /* chiamare la nostra funzione make_box - homogeneous = FALSE, spacing = 0,
         * expand = FALSE, fill = FALSE, padding = 0 */
        box2 = make_box (FALSE, 0, TRUE, FALSE, 0);
        gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
        gtk_widget_show (box2);
        
        /* Gli argomenti sono: homogeneous, spacing, expand, fill, padding */
        box2 = make_box (FALSE, 0, TRUE, TRUE, 0);
        gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
        gtk_widget_show (box2);
        
        /* Questo crea un separatore. Li conosceremo meglio in seguito, 
         * comunque sono piuttosto semplici. */
        separator = gtk_hseparator_new ();
        
        /* Impacchetta il separatore nella vbox. Ricordare che stiamo impacchettando
         * ognuno di questi oggetti in una vbox, cosicch&eacute; essi verranno
         * impacchettati verticalmente. */
        gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
        gtk_widget_show (separator);
        
        /* crea un'altra nuova etichetta e mostrala. */
        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);
        
        /* Gli argomenti sono: homogeneous, spacing, expand, fill, padding */
        box2 = make_box (TRUE, 0, TRUE, FALSE, 0);
        gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
        gtk_widget_show (box2);
        
        /* Gli argomenti sono: homogeneous, spacing, expand, fill, padding */
        box2 = make_box (TRUE, 0, TRUE, TRUE, 0);
        gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
        gtk_widget_show (box2);
        
        /* ancora un nuovo separatore. */
        separator = gtk_hseparator_new ();
        /* Gli ultimi 3 argumenti per gtk_box_pack_start sono: expand, fill, padding. */
        gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
        gtk_widget_show (separator);
        
        break;

    case 2:

        /* creare una nuova etichetta, ricordare che box1 e' la vbox creata 
         * vicino all'inizio di 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);
        
        /* Gli argomenti sono: homogeneous, spacing, expand, fill, padding */
        box2 = make_box (FALSE, 10, TRUE, FALSE, 0);
        gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
        gtk_widget_show (box2);
        
        /* Gli argomenti sono: homogeneous, spacing, expand, fill, padding */
        box2 = make_box (FALSE, 10, TRUE, TRUE, 0);
        gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
        gtk_widget_show (box2);
        
        separator = gtk_hseparator_new ();
        /* Gli ultimi tre arcomenti di gtk_box_pack_start sono: expand, fill, padding. */
        gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
        gtk_widget_show (separator);
        
        label = gtk_label_new ("gtk_hbox_new (FALSE, 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);
        
        /* Gli argomenti sono: homogeneous, spacing, expand, fill, padding */
        box2 = make_box (FALSE, 0, TRUE, FALSE, 10);
        gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
        gtk_widget_show (box2);
        
        /* Gli argomenti sono: homogeneous, spacing, expand, fill, padding */
        box2 = make_box (FALSE, 0, TRUE, TRUE, 10);
        gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
        gtk_widget_show (box2);
        
        separator = gtk_hseparator_new ();
        /* Gli ultimi tre argomenti di gtk_box_pack_start sono: expand, fill, padding. */
        gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
        gtk_widget_show (separator);
        break;
    
    case 3:

        /* Questo dimostra la possibilita' di usare use gtk_box_pack_end() per
         * giustificare gli oggetti a destra. Per prima cosa creiamo una
         * nuova scatola come prima. */
        box2 = make_box (FALSE, 0, FALSE, FALSE, 0);
        /* creiamo l'etichetta che sara' aggiunta alla fine. */
        label = gtk_label_new ("end");
        /* impacchettiamola usando gtk_box_pack_end(), cosa' che viene inserita
         * sul lato destro della hbox creata nella chiamata a the make_box(). */
        gtk_box_pack_end (GTK_BOX (box2), label, FALSE, FALSE, 0);
        /* mostriamo l'etichetta. */
        gtk_widget_show (label);
        
        /* impacchettiamo box2 in box1 (the vbox, ricordate? :) */
        gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
        gtk_widget_show (box2);
        
        /* un separatore per il fondo */
        separator = gtk_hseparator_new ();
        /* Questo assegna esplicitamente al separatore l'ampiezza di 400 pixel
         * e l'altezza di 5 pixel. Cio' fa si' che la hbox che abbiamo creato sia
         * anche essa larga 400 pixel, e che l'etichetta finale sia separata dalle
         * altre etichette nella hbox. In caso contrario, tutti gli oggetti nella
         * hbox sarebbero impacchettati il piu' vicino possibile. */
        gtk_widget_set_usize (separator, 400, 5);
        /* impacchetta il separatore nella vbox (box1) creata vicino all'inizio 
         * di main() */
        gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
        gtk_widget_show (separator);    
    }
    
    /* Creare un'altra nuova hbox.. ricordate che ne possiamo usare quante ne vogliamo! */
    quitbox = gtk_hbox_new (FALSE, 0);
    
    /* Il nostro bottone di uscita. */
    button = gtk_button_new_with_label ("Quit");
    

    /* Configuriamo il segnale per distruggere la finestra.  Ricordate che
     * ci&ograve; mander&agrave; alla finestra il segnale "destroy", che verr&agrave; catturato 
     * dal nostro gestore di segnali che abbiamo definito in precedenza. */
    gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
                               GTK_SIGNAL_FUNC (gtk_main_quit),
                               GTK_OBJECT (window));
    /* impacchetta il bottone in quitbox.
     * Gli ultimi tre argomenti di gtk_box_pack_start sono: expand, fill, padding. */
    gtk_box_pack_start (GTK_BOX (quitbox), button, TRUE, FALSE, 0);
    /* impacchetta quitbox nella vbox (box1) */
    gtk_box_pack_start (GTK_BOX (box1), quitbox, FALSE, FALSE, 0);
    
    /* impacchetta la vbox (box1), che ora contiene tutti i nostri oggetti,
     * nella finestra principale. */
    gtk_container_add (GTK_CONTAINER (window), box1);
    
    /* e mostra tutto quel che rimane */
    gtk_widget_show (button);
    gtk_widget_show (quitbox);
    
    gtk_widget_show (box1);
    /* Mostriamo la finestra alla fine in modo che tutto spunti fuori assieme. */
    gtk_widget_show (window);
    
    /* E, naturalmente, la nostra funzione main. */
    gtk_main ();

    /* Il controllo ritorna a questo punto quando viene chiamata gtk_main_quit(), 
     * ma non quando si usa gtk_exit. */
    
    return 0;
}
</PRE>
</CODE></BLOCKQUOTE>
<P>
<H2><A NAME="ss4.4">4.4 Impacchettamento con uso di Tabelle</A>
</H2>

<P>Diamo ora un'occhiata ad un altro modo di impacchettare - le Tabelle.
In certe situazioni, possono risultare estremamente utili.
<P>Usando le tabelle, creiamo una griglia in cui possiamo piazzare gli oggetti.
Gli oggetti possono occupare tanti spazi quanti ne specifichiamo.
<P>Naturalmente, la prima cosa da vedere &egrave; la funzione gtk_table_new:
<P>
<BLOCKQUOTE><CODE>
<PRE>
GtkWidget* gtk_table_new (gint rows,
                          gint columns,
                          gint homogeneous);
</PRE>
</CODE></BLOCKQUOTE>
<P>Il primo argomento rappresenta il numero di righe da mettere nella tabella,
mentre il secondo &egrave; ovviamente il numero di colonne.
<P>L'argomento homogeneous ha a che fare con il modo in cui le caselle della tabella
sono dimensionate. Se homogeneous ha il valore TRUE, le caselle sono ridimensionate
fino alla dimensione del pi&ugrave; grande oggetto contenuto nella tabelle. Se &egrave; FALSE, la
dimensione delle caselle&egrave; decisa dal pi&ugrave; alto oggetto in una certa riga e dal pi&ugrave;
largo oggetto in una stessa colonna.
<P>Le righe e le colonne sono disposte a partire da 0 fino a n, dove n &egrave; il numero
che era stato specificato nella chiamata a gtk_table_new. Cos&igrave;, se specificate 
rows = 2 e columns = 2, lo schema avr&agrave; questo aspetto:
<P>
<BLOCKQUOTE><CODE>
<PRE>
 0          1          2
0+----------+----------+
 |          |          |
1+----------+----------+
 |          |          |
2+----------+----------+
</PRE>
</CODE></BLOCKQUOTE>
<P>Notate che il sistema di coordinate ha origine nel vertice in alto a sinistra. Per
mettere un oggetto in una tabella, usate la seguente funzione:
<P>
<BLOCKQUOTE><CODE>
<PRE>
void gtk_table_attach (GtkTable      *table,
                       GtkWidget     *child,
                       gint           left_attach,
                       gint           right_attach,
                       gint           top_attach,
                       gint           bottom_attach,
                       gint           xoptions,
                       gint           yoptions,
                       gint           xpadding,
                       gint           ypadding);
</PRE>
</CODE></BLOCKQUOTE>
                                       
<P>In cui il primo argomento (``table'') &egrave; la tabella che avete creato e il secondo
(``child'') &egrave; l'oggetto che volete piazzare nella tabella.
<P>Gli argomenti ``attach''  (right, left, top, bottom)  specificano dove mettere l'oggetto
e quante caselle adoperare. Se volete mettere un bottone nella casella in basso a destra
nella nostra tabella 2x2, e volete che esso riempia SOLO quella casella, dovete porre
left_attach = 1, right_attach = 2, top_attach = 1, bottom_attach = 2.
<P>Se invece volete che un oggetto si prenda tutta la riga pi&ugrave; in alto nella nostra tabella
2x2, dovreste usare left_attach = 0, right_attach =2, top_attach = 0, 
bottom_attach = 1.
<P>Gli argomenti  ``xoptions'' e ``yoptions'' sono usati per specificare le opzioni di impacchettamento;
di essi si pu&ograve; fare l'OR in modo di ottenere opzioni multiple.
<P>Le opzioni sono:
<UL>
<LI>GTK_FILL - Se la parte di tabella in cui si vuole inserire il widget &egrave; pi&ugrave; 
grande dell'oggetto, e se si specifica GTK_FILL, l'oggetto viene espanso fino ad
occupare tutto lo spazio disponibile.
</LI>
<LI>GTK_SHRINK - Se si alloca all'oggetto nella tabella meno spazio del necessario
(di solito succede quando l'utente ridimensiona la finestra), allora normalmente
l'oggetto verrebbe spinto fuori dal fondo della finestra fino a sparire.
Se invece si specifica GTK_SHRINK is specified, gli oggetti si rimpiccioliscono
assieme alla tabella.
</LI>
<LI>GTK_EXPAND - Questo fa s&igrave; che la tabella si espanda fino ad occupare tutto lo 
spazio che rimane nella finestra.</LI>
</UL>
<P>Il riempimento funziona come nelle scatole, con la creazione di un'area vuota
attorno all'oggetto la cui dimensione viene specificata in pixel.
<P>La funzione gtk_table_attach() ha UN MUCCHIO di opzioni. Quindi, ecco una scorciatoia:
<P>
<BLOCKQUOTE><CODE>
<PRE>
void gtk_table_attach_defaults (GtkTable   *table,
                                GtkWidget  *widget,
                                gint        left_attach,
                                gint        right_attach,
                                gint        top_attach,
                                gint        bottom_attach);
</PRE>
</CODE></BLOCKQUOTE>
<P>Le xoptions e yoptions vengono posti per difetto a GTK_FILL | GTK_EXPAND, e sia xpadding
che ypadding vengono posti a 0. Il resto degli argomenti sono identici a quelli della funzione
precedente.
<P>Ci sono poi le funzioni gtk_table_set_row_spacing() and gtk_table_set_col_spacing().
Queste mettono dello spazio fra le righe (o colonne)in corrispondenza di una specifica
riga (o colonna).
<P>
<BLOCKQUOTE><CODE>
<PRE>
void gtk_table_set_row_spacing (GtkTable      *table,
                                gint           row,
                                gint           spacing);
</PRE>
</CODE></BLOCKQUOTE>

e
<BLOCKQUOTE><CODE>
<PRE>
void       gtk_table_set_col_spacing  (GtkTable      *table,
                                       gint           column,
                                       gint           spacing);
</PRE>
</CODE></BLOCKQUOTE>
<P>Notate che per le colonne lo spazio viene posto alla destra della colonna, mentre
per le righe lo spazio viene posto al di sotto della riga.
<P>Si pu&ograve; poi inserire una spaziatura identica fra tutte le righe e/o colonne usando:
<P>
<BLOCKQUOTE><CODE>
<PRE>
void gtk_table_set_row_spacings (GtkTable *table,
                                 gint      spacing);
</PRE>
</CODE></BLOCKQUOTE>
<P>e
<BLOCKQUOTE><CODE>
<PRE>
void gtk_table_set_col_spacings (GtkTable  *table,
                                 gint       spacing);
</PRE>
</CODE></BLOCKQUOTE>
<P>Notate che con queste chiamate,  all'ultima riga e all'ultima colonna
non viene assegnata alcuna spaziatura.
<P>
<H2><A NAME="ss4.5">4.5 Esempio di Impacchettamento con Tabelle</A>
 </H2>

<P>In questo esempio creiamo una finestra avente tre bottoni disposti
in una tabella 2x2. I primi due bottoni li mettiamo nella riga superiore.
Un terzo bottone, quit, lo mettiamo nella riga inferioe, in modo da
comprendere entrambe le colonne. Ci&ograve; significa che dovremmo
avere qualcosa di questo tipo:
<P> <CENTER >
<IMG SRC="gtk_tut_table.gif" VSPACE="15" HSPACE="10" 
ALT="Table Packing Example Image" WIDTH="180" HEIGHT="120"
> </CENTER
 >
<P>Ecco il codice sorgente:
<P>
<BLOCKQUOTE><CODE>
<PRE>
/* table.c */
#include &lt;gtk/gtk.h>

/* la nostra funzione di ritorno.
 * i dati passati a questa funzione vengono stampati su stdout */
void callback (GtkWidget *widget, gpointer data)
{
    g_print ("Hello again - %s was pressed\n", (char *) data);
}

/* questa funzione fa uscire dal programma */
void delete_event (GtkWidget *widget, gpointer data)
{
    gtk_main_quit ();
}

int main (int argc, char *argv[])
{
    GtkWidget *window;
    GtkWidget *button;
    GtkWidget *table;

    gtk_init (&amp;argc, &amp;argv);

    /* creiamo una nova finestra */
    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

    /* predisponiamo il titolo per la finestra */
    gtk_window_set_title (GTK_WINDOW (window), "Table");

    /* creiamo un gestore per delete_event che esca immediatamente
     * da GTK. */
    gtk_signal_connect (GTK_OBJECT (window), "delete_event",
                        GTK_SIGNAL_FUNC (delete_event), NULL);

    /* regoliamo la larghezza del bordo della finestra. */
    gtk_container_border_width (GTK_CONTAINER (window), 20);

    /* creiamo una tabella 2x2 */
    table = gtk_table_new (2, 2, TRUE);

    /* mettiamo la tabella nella finesta principale */
    gtk_container_add (GTK_CONTAINER (window), table);

    /*creiamo il primo bottone */
    button = gtk_button_new_with_label ("button 1");
    /* quando viene premuto il bottone, chiamiamo la funzione di ritorno
     * con un puntatore a "button 1"come argomento */
    gtk_signal_connect (GTK_OBJECT (button), "clicked",
              GTK_SIGNAL_FUNC (callback), (gpointer) "button 1");


    /* inseriamo il bottone 1 nel quadrante in alto a sinistra della tabella */
    gtk_table_attach_defaults (GTK_TABLE(table), button, 0, 1, 0, 1);

    gtk_widget_show (button);

    /* creiamo il secondo bottone */

    button = gtk_button_new_with_label ("button 2");

    /* quando si preme il bottone, chiamamo la funzione di ritorno
     * con un puntatore a "button 2"come argomento */
    gtk_signal_connect (GTK_OBJECT (button), "clicked",
              GTK_SIGNAL_FUNC (callback), (gpointer) "button 2");
    /* inseriamo il secondo bottone nel quadrate in alto a destra della tbella */
    gtk_table_attach_defaults (GTK_TABLE(table), button, 1, 2, 0, 1);

    gtk_widget_show (button);

    /* creiamo il botone "Quit" */
    button = gtk_button_new_with_label ("Quit");

    /* quando viene premuto questo bottone, chiamiamo la funzione "delete_event"
     * e si esce dal programma */
    gtk_signal_connect (GTK_OBJECT (button), "clicked",
                        GTK_SIGNAL_FUNC (delete_event), NULL);

    /* inseriamo il pulsante quit nelle due casele in basso della tabella */
    gtk_table_attach_defaults (GTK_TABLE(table), button, 0, 2, 1, 2);

    gtk_widget_show (button);

    gtk_widget_show (table);
    gtk_widget_show (window);

    gtk_main ();

    return 0;
}
</PRE>
</CODE></BLOCKQUOTE>
<P>
<HR NOSHADE>
<A HREF="gtk_tut_it-5.html">Avanti</A>
<A HREF="gtk_tut_it-3.html">Indietro</A>
<A HREF="gtk_tut_it.html#toc4">Indice</A>
</BODY>
</HTML>