« Tcl: "Hello World" e introduzioneAppunti di Tcl/TkTk: opzioni standard dei widget »

Tk

comando pack

Una volta creato un widget occorre posizionarlo all'interno del suo widget genitore e farlo visualizzare. In Tk, come in Xt, i singoli widget non controllano i loro aspetti geometrici. Ogni widget può specificare una sua dimensione, ma questa è solo una dimensione preferenziale, nel senso che la dimensione che gli viene assegnata potrebbe non coincidere con quella preferita (potrebbe essere anche minore e il widget dovrà cavarsela per cercare di visualizzare al meglio il suo contenuto). La disposizione dei widget viene fatta dai gestori della geometria (geometry manager) che, tenendo conto delle dimensioni preferenziali di ciascun widget, della dimensione del widget genitore e del tipo di disposizione desiderata (layout), calcolano e assegnano la posizione e la dimensione a ciascun widget.

In questo modo con gli stessi widget si possono utilizzare diversi gestori di geometria, ciascuno con algoritmi di posizionamento differenti (ad es. si possono disporre widget per colonna o per riga oppure in una griglia), fermo restante che in ogni momento un solo geometry manager gestisce un certo widget.

Il comando pack(n) di Tcl viene usato per comunicare con uno dei geometry manager incorporato in Tk e detto packer, il quale ha molte funzionalità ma il modo più semplice di utilizzarlo è di passargli i percorsi dei widget da pacchettare per incolonnarli:

button .a -text "long text"
button .b -text short
pack .a .b
pack .a .b

In questo semplice esempio il comando pack impachetta i due widget .a e .b nell'ordine specificato all'interno del loro widget genitore (che chiaramente è la finestra dell'applicazione, di percorso .). Notate che le dimensioni della finestra principale vengono impostate in modo che possa contenere i widget che vi vengono pacchettati, senza alcuno spazio in più o in meno. Ma provate a ingrandire la finestra ed ecco cosa succede:

finestra ingrandita

Come potete vedere pack(n) ha impacchettato nell'alto (infatti per default vale l'opzione -side top) della cavità (lo spazio rimasto libero, inizialmente l'intera area del master) dell'oggetto contenitore (detto anche master, mentre gli oggetti contenuti vengono detti slave). In questa cavità pack(n) assegna un appezzamento rettangolare (parcel) ad ogni widget. Per default vale l'opzione -anchor center ossia ogni slave viene centrato nell'appezzamento ad esso assegnato. Nel nostro semplice esempio di pacchettamento in verticale la larghezza dell'appezzamento coincide con la larghezza della cavità (della finestra dell'applicazione nel nostro caso), mentre l'altezza è quella richiesta da ogni widget. Dopo aver allocato l'appezzamento, pack(n) sceglie le dimensioni dello slave, che in questo caso sono scelte pari a quelle richieste e infine posiziona lo slave sul suo appezzamento (nel nostro caso centrandolo).

Provate ora a ridurre le dimensioni della finestra rispetto alla sua dimensione minima di default ed ecco due fotogrammi che lasciano intendere cosa succede:

finestra ridotta

finestra ulteriormente ridotta

La cavità è diventata troppo piccola per poter rispettare le dimensioni preferenziali degli slave; agli slave viene assegnato giusto lo spazio che rimane nella cavità. Nell'ultima immagine, quando si pacchetta .b, non è rimasto nessuno spazio libero, la cavità è vuota e perciò il widget .b non viene proprio visualizzato: riapparirà quando la finestra verrà sufficientemente ingrandita.

Supponendo che invece di pacchettare nell'alto della cavità volete impachettare a sinistra (left) o nel basso (bottom) oppure a destra (right), aggiungete in fondo l'opzione -side ed ecco cosa cambia:

pack .a .b -side top
pack .a .b -side top

pack .a .b -side bottom
pack .a .b -side bottom

pack .a .b -side left
pack .a .b -side left

pack .a .b -side right
pack .a .b -side right

Potete anche scambiare l'ordine in cui elencate gli slave e vedere cosa succede.

L'opzione -expand per default è 0 (o no), ma se la impostate ad 1 (o yes), fa sì che gli slave si espandano in modo da consumare tutto lo spazio disponibile nel loro master. Più precisamente, lo spazio extra orizzontale del master viene distribuito tra gli slave che hanno l'attributo expand settato a 1 e che sono stati pacchettati con l'opzione -side left o right, mentre quello verticale extra tra gli slave espandibili pacchettati con -side top o bottom. Ecco un esempio:

pack .a .b -expand 1
pack .a .b -expand 1

pack .a .b -expand 1, allargato
pack .a .b -expand 1, finestra allargata

Supponete che volete che i due bottoni abbiano la stessa larghezza e pari a quella della finestra che li contiene, anche se il testo contenuto ha larghezza diversa o la finestra viene ridimensionata. Potete usare l'opzione -fill x per stiracchiare lo slave orizzontalmente in modo che riempia l'intera larghezza della parcella ad esso assegnata:

pack .a .b -fill x
pack .a .b -fill x

pack .a .b -fill x, allargato
pack .a .b -fill x, finestra allargata

pack .a .b -side left -fill y, allargato
pack .a .b -side left -fill y, finestra allargata

Infine proviamo a combinare le opzioni -expand e -fill:

pack .a .b -fill both -expand 1, allargato
pack .a .b -fill both -expand 1, finestra allargata

Per tpad dovremo pacchettare una textarea con due scrollbar (una verticale ed un'altra orizzontale). Vogliamo che l'altezza della scrollbar verticale sia la stessa di quella della textarea e che la larghezza della scrollbar orizzontale sia esattamente la stessa di quella della textarea. Vogliamo inoltre che ridimensionando la finestra (entro un certo limite) le scrollbar rimangano sempre visibili.

Non è possibile ottenere questo layout usando solo pack(n) o una combinazione di pack(n) e frame(n). Bisogna ricorrere ad una disposizione a griglia, simile ad una tabella HTML elastica usata per il layout:

text .text
scrollbar .vscroll
scrollbar .hscroll -orient horizontal

grid .text -row 0 -column 0 -sticky news
grid .vscroll -row 0 -column 1 -sticky ns
grid .hscroll -row 1 -column 0 -sticky ew
grid rowconfigure . 0 -weight 1
grid columnconfigure . 0 -weight 1
esempio di disposizione a griglia

Questa non è una descrizione completa o precisa di pack(n), quindi raccomando di leggere attentamente la manpage pack(n), che adesso però dovrebbe apparirvi più chiara. Gli altri geometry manager sono grid(n) e place(n), per cui rimando alle rispettive manpage. Vedremo comunque qualche altro esempio d'uso anche di questi in seguito.

« Tcl: "Hello World" e introduzioneAppunti di Tcl/TkTk: opzioni standard dei widget »