ioProgrammo N°22, Febbraio 1999 ©Copyright DIEMME Editori
listbox pathName ?opzioni? scrollbar pathName ?opzioni?dove pathName (non mi stancherò mai di ricordarlo) è il nome dello strumento in riferimento alla gerarchia degli altri strumenti ai quali appartiene. A questo punto direi di sospendere le divagazioni teoriche e passare sl codice con un esempio. Ci proponiamo di scrivere un breve programma che consenta la scelta di un colore da un listbox e che automaticamente dipinga lo sfondo della finestra con il colore appena scelto. I nomi dei colori verranno scelti dal file rgb.txt della directory /var/X11R6/lib. Si noti che in Linux questo file è l'unico nostro riferimento per conoscere i nomi delle varie combinazioni dei tre colori fondamentali: rosso, verde e blu.
set rgb [open "/var/X11R6/lib/rgb.txt" r] # assegno a rgb l'identificatore per il file\ rgb.txt che verrà aperto in sola lettura set k 0 while {[gets $rgb line] != -1} { # inizio a leggere i file riga per riga fino alla fine\ e assegno il contenuto di una riga alla variabile line set colore [split $line "\t"] # per ogni riga creo la lista colore i cui elementi\ sono le porzioni della riga separate dal tab if {[regexp {^[aA-zZ]} [lindex $colore 2]] && \ ![regexp { } [lindex $colore 2]]} { set color($k) [lindex $colore 2] incr k } # se il terzo elemento della lista colore inizia\ con una lettera e se non contiene spazi, creo un\ nuovo elemento dell'arry color. Questo array alla\ fine del ciclo while conterrà tutti i nomi validi dei\ colori del file rgb.txt } frame .frame # definisco un frame per la listbox scrollbar .frame.scroll -command ".frame.list yview" # definisco la scrollbar appartente al frame\ -command specifica il comando yview usato per\ lo scrolling verticale della listbox .frame.list listbox .frame.list -yscroll ".frame.scroll set" \ -width 20 -height 16 -setgrid 1 # definisco la listbox larga 20 caratteri e alta 16\ -yscroll associa il comando di scrolling con la scrollbar pack .frame.list .frame.scroll -side left -fill y -expand 1 # affianco la listbox e la scrollbar bind .frame.list <Double-1> { . configure -bg [selection get] } # associo l'evento "doppio clic del pulsante di sinistra\ del mouse" alla listbox. Il doppio clic sul nome del colore\ scelto cambia il colore di sfondo della finestra set i 0 while {$i < $k} { .frame.list insert $i $color($i) incr i } # riempie la listbox con i nomi dei\ colori dell'array color pack .frame -padx 20 -pady 20 #posiziona l'oggetto frame con un margine\ di 20 pixel dai bordi della finestra
frame .f -width 100 -height 100 bind .f <Button-1> {puts "Button 1 premuto"} bind .f <Button-2> {puts "Button 2 premuto"} bind .f <Button-3> {puts "Button 3 premuto"} bind .f <ButtonRelease-1> {puts "Button 1 rilasciato"} bind .f <Double-Button-1> {puts "Doppio click Button 1"} bind .f <Any-Motion> {puts "Posizione %x,%y"} pack .fAbbiamo infatti associato ad un frame tutti gli eventi del mouse. Cliccando o spostano il mouse sopra il frame verranno stampate sulla finestra Xterm alcune note curiose.
msqladmin create usersPoi con il comando "msql users" creiamo la tabella "users". Al prompt mSQL> si immette il comando \e. Verrà aperto un editor in cui scriveremo le seguenti linee:
create table users ( cognome char(30) nome char(30) indirizzo char(50) telefono char(15) data char(8) username char(8) password char(10) )
Salviamo il contenuto dell'editor e al prompt mSQL> immettiamo il comando \g che eseguirà la query "create table users".
Ottimo, il database è stato creato.
Ora passiamo al codice tcl/tk ma prima diamo un'occhiata al layout del nostro programma (Figura 2).
Iniziamo dalla geometria della finestra dell'applicazione
#!/usr/bin/wish package require msqltcl # include la libreria msqltcl wm geometry . 320x450 # finestra del programma larga 320 e alta 450 pixel wm title . "XmSQL Users" # titolo della finestra . configure -bg #aaffcc # colore di sfondo della finestra wm resizable . 0 0 # finetra non ridimensionabilePoi passiamo alla barra dei menu rappresentata dal frame .f1
frame .f1 -bd 2 -relief groove # imposto la barra dei menu menubutton .f1.m1 -text "File" -menu .f1.m1.mm1 menubutton .f1.m2 -text "Help" -menu .f1.m2.mm2 # predispone i due menu \ -text e' l'etichetta del menu\ -menu indica il menu contenente tutte le opzioni menu .f1.m1.mm1 menu .f1.m2.mm2 # imposta i due menu a tendina .f1.m1.mm1 add command -command lista_tutto -label "Lista tutto" .f1.m1.mm1 add command -command cancella_tutto -label "Cancella tutto" .f1.m1.mm1 add command -command exit -label "Esci" .f1.m2.mm2 add command -command help -label "Guida" .f1.m2.mm2 add command -command help -label "Informazioni" # riempie i due menu a tendina\ -command associa ad ogni voce di menu un comando tcl pack .f1.m1 -side left pack .f1.m2 -side right pack .f1 -fill x # posiziona i due menu, uno alla sinistra e l'altro\ alla detra della barra dei menuOra è il turno degli strumenti che permettono la ricerca per cognome, impacchettati nel frame .f2
frame .f2 -bg #aaffcc label .f2.l1 -text "Cognome:" -bg #aaffcc entry .f2.e2 -bg white -textvariable cerca button .f2.b2 -text "Cerca" -command {cerca} pack .f2.l1 -side left pack .f2.e2 -side left pack .f2.b2 -side left pack .f2Proseguiamo con i frame centrali, quelli con le etichette ed i campi di input usati per immettere o modificare i dati degli utenti
frame .f3 -bg #aae5e5 -bd 3 -relief raised # Il frame delle etichette frame .f3.fsx -bg #aae5e5 set etic {Cognome: Nome: Indirizzo: Telefono: \ "Data login:" USERNAME: PASSWORD:} set k 1 foreach i $etic { label .f3.fsx.l$k -text $i -bg #aae5e5 pack .f3.fsx.l$k -anchor nw -pady 4 incr k } unset i # e quello dei campi di input frame .f3.fdx -bg #aae5e5 set var {cognome nome indirizzo telefono \ data username password} set k 1 foreach i $var { entry .f3.fdx.e$k -bg white -textvariable $i pack .f3.fdx.e$k -pady 2 -anchor nw incr k } # ora li impacchettiamo pack .f3.fsx -side left -ipadx 5 -padx 5 -pady 3 pack .f3.fdx -side left -padx 5 -pady 3 pack .f3Ci serve un altro frame per posizionare i pulsanti "Nuovo", "Aggiorna" e "Cancella", ai quali verranno associate le procedure che permetteranno l'inserimento, la modifica e la cancellazione dei dati di un utente
frame .f4 -bg #aaffcc button .f4.b1 -text "Nuovo" -command nuovo button .f4.b2 -text "Aggiorna" -command aggiorna button .f4.b3 -text "Cancella" -command cancella pack .f4.b1 -side left -padx .4c pack .f4.b2 -side left -padx .4c pack .f4.b3 -side left -padx .4c pack .f4 -pady 3Gli ultimi strumenti sono un text e due scrollbar, posizionati nel frame .f5. L'oggetto text di solito viene usato nella programmazione di editor poiché consente la scrittura di testo su un area della finestra. Noi invece lo useremo per l'output di tutti i dati del database.
frame .f5 text .f5.text -wrap none \ -xscrollcommand [list .f5.xscroll set] \ -yscrollcommand [list .f5.yscroll set] \ -bg #f0f0f0 scrollbar .f5.xscroll -orient horizontal \ -command [list .f5.text xview] scrollbar .f5.yscroll -orient vertical \ -command [list .f5.text yview] pack .f5.xscroll -side bottom -fill x pack .f5.yscroll -side right -fill y pack .f5.text -side left -fill x -expand 1 pack .f5Benissimo. La nostra applicazione è quasi pronta. Ora ci concentriamo sulle procedure che eseguiranno le query sql.
set db [msqlconnect localhost] msqluse $db users proc lista_tutto {} { # visualizza i dati di tutti gli utenti global db global cognome nome indirizzo telefono data username password .f5.text delete 0.0 end # cancella il contenuto del widget text msqlsel $db {select * from users order by cognome} msqlmap $db { cognome nome indirizzo telefono data username password } { .f5.text insert 0.0 \ "$username $cognome $nome $indirizzo $telefono $data $password\n" } } proc cancella_tutto {} { # svuota il db global db msqlsel $db "delete from users" } proc cerca {} { # visualizza i dati di un utente con una\ ricerca per cognome global db global cerca set k 1 while {$k <= 7} { .f3.fdx.e$k delete 0 end # cancella il contenuto di tutti i campi di input incr k } msqlsel $db "select * from users where cognome like '%$cerca%'" set result [msqlnext $db] set k 1 foreach i $result { .f3.fdx.e$k insert 0 $i # riempie tutti i campi di input incr k } } proc nuovo {} { # nuovi dati nel db global db global cognome nome indirizzo telefono data username password msqlsel $db "insert into users (cognome, nome, indirizzo, \ telefono, data, username, password) values ('$cognome', '$nome', \ '$indirizzo', '$telefono', '$data', '$username', '$password')" } proc aggiorna {} { # modifica i dati di un utente global db global cognome nome indirizzo telefono data username password msqlsel $db "update users set cognome = '$cognome', nome = '$nome',\ indirizzo = '$indirizzo', telefono = '$telefono', data = '$data',\ username='$username', password='$password' where username = '$username'" } proc cancella {} { # cancella i dati di un utente global db global username msqlsel $db "delete from users where username = '$username'" } proc help {} { # il menu help dà alcune informazioni sul programma tk_messageBox -icon info -type ok -message \ "XmSQL Users\nper i lettori di ioProgrammo" }Il nostro programma è pronto e sarà uguale a quello visualizzato in figura 3. Vi sarete accorti che nel codice mancano i controlli sugli errori. Li potreste scrivere voi, almeno sulle istruzioni sql: che ne dite?
Supponendo di aver già installato mSQL 1.0.16 (per default /usr/local/Minerva/bin) la compilazione di msqltcl-1.99 non dovrebbe essere problematica. E' sufficiente leggere con attenzione i file README ed INSTALL e fornire i parametri corretti al comando configure. Sei parametri specificano il path delle librerie di tcl, tk e mSQL, mentre il settimo abiliterà il caricamento dinamico della libreria. Dopo di che possiamo eseguire in successione i comandi make e make install. Se siamo stai bravi nella directory /usr/local/lib troveremo i file di libreria msqltcl, msqlwish e msqltcl.so. A questo punto non ci resta che informare tcl della presenza di una nuova libreria con l'esecuzione della seguente riga di codice
pkg_mkIndex /usr/local/lib msqltcl.soQuesto comando aggiorna il file indice delle librerie supportate da tcl. Successivamente saremo in grado di includere la libreria nello script usando il comando "package require msqltcl.so". Quest'ultima istruzione è valida solo nel caso in cui abbiamo compilato una libreria dinamica (il settimo parametro del comando configure), altrimenti bisogna usare il comando di sistema "load msqltcl.so". Nell'esempio di questo articolo useremo solo alcuni dei comandi di msqltcl e precisamente
msqlconnect ?hostname? (apre una connessione al server msqld e restituisce un handle).
msqluse handle dbname (abilita l'uso di un database associato all'handle).
msqlsel handle sql-statement (esegue una query sql sul database e restituisce il numero di record prodotti dalla query).
msqlnext handle (restituisce una lista con i valori dei campi del record successivo della query).
msqlmap handle binding-list script (itera l'esecuzione di codice tcl per ogni record della query. Ogni elemento della binding-list punta al nome di ogni campo della tabella prodotta dalla query).
Data creazione HTML: Marzo 1999
Autore: Francesco Munaretto
E-mail: NoSpam@thank.you