Guizero è un framework per creare interfacce grafiche in python semplice da usare, multipittaforma e, a detta dei suoi sviluppatori, adatto anche ai bambini. Per tale ragione mi sembra lo strumento perfetto su cui soffermarsi per un tutorial adatto a un neofita come me.
La fonte da cui prendo i dati qui illustrati è il sito ufficiale del progetto (in inglese)
Prima di iniziare questo tutorial ovviamente si consiglia la lettura di quello di base del python
Installazione
Guizero è un pacchetto di python che va installato tramite pip per essere utilizzato, mediante il comando
pip3 install guizero
è possibile inoltre installare strumenti un po’ più avanzati per la gestione delle immagini mediante questo comando:
pip3 install guizero[images]
E’ possibile su linux installare guizero anche via apt (si rimanda per i pochi interessati al tutorial in inglese). Utilizzare in ogni caso un solo metodo di installazione.
Creazione di una singola finestra vuota
from guizero import App
app=App(title=”nuova app”)
app.display() #questo crea solo una finestra con il titolo “nuova app”
Aggiungere un testo fisso
per aggiungere del testo fisso alla finestra basta fare una semplice modifica al codice:
from guizero import App, Text
app=App(title=”nuova app”)
messaggio= Text(app, text=”testo dentro la finestra”)
app.display()
Aggiungere un bottone premibile
E’ possibile anche aggiungere ad esempio un bottone che quando è premuto cambia il testo mostrato:
from guizero import App, Text, PushButton
def ChangeMessage(): #questa funzione viene chiamata quando si preme il bottone, è bene scrivere le funzioni evento prima di instanziare la app
….message.value(“hai premuto il bottone”)
app=App(title=”nuova app”)
messaggio= Text(app, text=”testo dentro la finestra”)
button=PushButton(app, text=”premimi”, command=ChangeMessage())
app.display()
Utilizzare i widgets
Ogni app fatta con guizero è composta da widgets interagenti.
Tutti i widget del programma vanno inseriti fra la funzione App() e la funzione app.display()
Aggiungere una finestra di input testo
testoinp=TextBox(app) #ove app è l’istanza attiva della classe App definita da guizero e testoinp l’oggett
Visualizzazione dei widget a schermo
I seguenti metodi consentono di abuilitare/disabilitare o anche mostrare/nascondere le istanze dei widgets a schermo
nomeistanza.show() #mostra a schermo
nomeistanza.hide() #nasconde
nomeistanza.enable() #abilita
nomeistanza.disable() #disabilita
I widget possono essere anche distrutti mediante:
nomeistanza.destroy()
tuttavia si raccomanda di non usare questo metodo per evitare problemi
Finestre ulteriori
E’ possibile aprire sottofinestre da quella principale mediante Window()
sottofinestra=Window(app, title=”sottofinestra”)
#Ci si può poi riferire alla sottofinestra allo stesso modo della principale per metterci ulteriori widget: esempio
testo=Text(window,text=”questo testo comparirà nella seconda finestra”)
Mediante i metodi show() e hide() è possibile aprire e chiudere le sottofinestre
Se si vuole impedire di usare la finestra principale quando quella secondaria è aèperta è possibile modificare così la funzione show()
window.show(wait=True)
Layout
La disposizione degli elementi di un programma può essere definita automaticamente o mediante una griglia mediante questa singola riga di codice (una a scelta scritta dopo la dichiarazione della variabile app:
app = App(layout=“auto”)
oppure
app = App(layout=“grid”)
Se nessun layout è specificato di default vale l’impostazione “auto”
Per definire la posizione di un oggetto con il default auto bisogna specificare nella sua dichiarazione la variabile “align”. esempio:
testo_in_cima = Text(app, text=“in cima”, align=“top”)
Align può avere i seguenti valori: top, bottom, left, right
Se si usa lo stesso valore di align più volte di fila li oggetti verranno disposti in sequenza dal primo all’ultimo.
Le variabili “width” ed “height” permettono di definire le dimensioni dei widget. Specificando come valore “fill” riempiranno tutta la finestra lungo quella dimensione. Se si usa fill con più widgets lo spazio viene diviso equamente.
Se invece si usa il layout “grid” la posizione di un oggetto è definita dalle sue coordinate specificate nella variabile grid. Esempio:
testo_xy = Text(app, text=“in cima”, grid=[x,y]) #ove x e y sono i valori delle coordinate
All’interno di una griglia è anche possibile specificare la variabile align, per disporre più oggetti in sequenza nell’ambito della stessa coordinata. Esempio di form compilabile così creato:
etichetta_nome = Text(app, text=“Nome”, grid=[0,0], align=“left”)
nome = TextBox(app, grid=[1,0])
etichetta_cognome = Text(app, text=“Cognome”, grid=[0,1], align=“left”)
cognome= TextBox(app, grid=[1,1])
Mediante la griglia è anche possibile specificare che un widget ha una dimensone maggore di una cella:
testo_largo=Text(app,text=”testo largo”,grid[x,y,dx,dy])
#ove dx e dy sono le dimensioni oltre l’unità dell’oggetto lungo l’asse scelto.
Widget box
Mediante il widget box è possibile organizzare i widget in sottoinsiemi. Esempio:
scatola = Box(app, width=“fill”, align=“top”,border=true)
#se border è settato su true i bordi del widget saranno visibili
titolo = Text(scatola, text=“titolo”, align=“top”)
testosotto=Text(scatola,text=”testo di sotto”, align=”bottom”)
E’ possibile anche inserire widget box dentro altri widget box.
Pop-up
Queste funzioni possono essere inserite nel programma per aprire diversi tipi di popup a schermo. In questi esempi la variabile app si riferisce sempre al programma:
app.warn(“titolo”,”testo”)
#popup con icona di avvertimento
app.info(“titolo”,”testo”)
#popup con icona di informazione
app.error(“titolo”,”testo”)
#popup con icona di errore
app.yesno(“titolo”,”testo”)
#popup che consente di scegliere con 2 bottoni si o no. Se viene premuto si ritorna true, se viene premuto no ritorna false
app.question(“titolo”,”testo”,valore iniziale=”abcde”)
#popup con possibilità di introdurre un testo che viene restituito dalla funzione premendo il tasto OK. se nessun testo viene inserito ritorna il valore None
app.select_file(“titolo”, folder=” *. *”. filetypes=[]”tutti i formati”,”*.*”]], save=false. filename=”nomefile”)
#permette di selezionare un file. Se save è settato su true si commuta in “salva con nome”
app.select_folder(“titolo”, folder=”\percorso\cartella”)
#permette di selezionare una cartella
app.select_color(color=None)
#permette di selezionare un colore, restituito come output nel formato #rrggbb (esadecimale). Premendo annulla restituisce None.
Altre funzioni importanti:
app.destroy()
#chiude il programma se usata sull’istanza principale
app.when_closed #vale true se si cerca di chiudere il programma, utile per programmmare un popup di conferma chiusura
Dimensioni:
Come detto prima le dimensioni dei widget possono essere specificate mediante le variabili width ed height; Usando “fill” come impostazione il widget riempie tutto lo spazio disponibile, mentre usando un valore numerico si può definire la dimensione del widget in modo specifico, tuttavia l’unità di misura varia da widget a widget e non tutti accettano il settaggio fill. Qui sotto un riassunto breve:
Box accetta fill e le dimensioni sono espresse in pixel. Se si sceglie di settare vanno specificati sia width sia height
Buttongroup accetta fill e le dimensioni sono espresse in caratteri. Height viene diviso per il numero di bottoni
Checkbox accetta fill e le dimensioni sono espresse in caratteri
Combo accetta fill e le dimensioni sono espresse in caratteri
Listbox accetta fill e le dimensioni sono espresse in pixel
Picture non accetta fill e le dimensioni sono espresse in pixel (vedremo meglio quando si parlerà di immagini)
PushButton accetta fill e le dimensioni sono espresse in caratteri
PushButton con immagini non accetta fill e le dimensioni sono espresse in pixel
Slider accetta fill e le dimensioni sono espresse in pixel
Text accetta fill e le dimensioni sono espresse in caratteri
TextBox accetta fill e le dimensioni sono espresse in caratteri. E’ possibile esprimere solo width
Waffle non accetta fill e le dimensioni sono espresse in pixel
Colori
In guizero i colori sono definibili in 3 modi:
- per nome
- in esadecimale (come già visto prima, questa è la modalità standard con cui il programma gestisce i colori fra le funzioni)
- in decimale
Ad esempio per definire il colore dello sfondo (rosso) della finestra:
app=App(bg=”red”)
app=App(bg=”#ff0000″)
app=App(bg=(255,0,0))
Il colore di un testo può essere definito così:
text=Text(app,text=”testo verde”)
text.text_color=”green”
#se text.text_color=None il colore sarà quello di default
qui è disponibile un elenco dei nomi dei colori supportati
qui trovate un convertitore fra i vari modi per definire i colori
Qui sotto le definizioni nei 3 modi dei colori più comuni:
- white =
#ffffff (255,255,255) - black =
#000000 (0,0,0) - red =
#ff0000 (255,0,0) - green =
#00ff00 (0,255,0) - blue =
#0000ff (0,0,255) - yellow =
#ffff00 (255,255,0)
Immagini
Inserire un’ immagine in un app è semplicissimo. Ricordate da installare pillow da pip o da apt per un migliore e più completo supporto a diversi formati, come detto in introduzione.
from guizero import App, Picture
app=App()
immagine=Picture(app, image=”immagine.jpg”)
app.display()
E’ necessario avere pillow sul sistema per riscalare un’immagine all’interno del programma, in caso contrario questa sarà tagliata. Pillow consente abche di vedere le GIF animate.
Loop, cicli e sleep
Quando si vuole modificare nel tempo una GUI di guizero non è possibile dichiarare ad esempio un ciclo while all’interno dell’interfaccia per creare un cronometro, in quanto le GUI sono già di per se cicli infiniti che si chiudono con app.destroy(). Se farete questo il programma andrà quindi in crash.
Per lavorare su variazioni periodiche la cosa migliore è creare una funzione di callback come quella qui in esempio:
from guizero import App, Text
def contatore():
….text.value=int(text.value)+1
app=App()
text=Text(app,text=”1″)
text.repeat(1000, contatore) #questo ripete la funzione contatore ogni 1000 ms
app.display()
Eventi
E’ possibile che il programma venga impostato per eseguire qualunque azione all’accadere di alcuni eventi all’interno dell’interfaccia grafica. Questi sono gli eventi disponibili in guizero richiamabili mediante metodo al widget scelto all’interno di funzioni:
widget.when_clicked (clic del mouse)
widget.when_double_clicked (doppio clic del mouse)
widget.when_left_button_pressed (pressione del tasto sinistro del mouse)
widget.when_left_button_released (rilascio del tasto sinistro del mouse)
widget.when_right_button_pressed (pressione del tasto destro del mouse)
widget.when_right_button_released (rilascio del tasto destro del mouse)
widget.when_key_pressed (pressione di qualunque tasto sulla tastiera)
widget.when_key_released (rilascio di qualunque tasto sulla tastiera)
widget.when_mouse_enters (il puntatore del mouse entra nel widget)
widget.when_mouse_leaves (il puntatore del mouse abbandona il widget)
widget.when_mouse_dragged (il puntatore del mouse viene trascinato sul widget)
widget.when_resized (quando il widget viene ridimensionato)
Esempio
from guizero import App, Text
def cambiacolore():
….text.text_color=”red”
app=App()
text=Text(app,”testo colorato”)
text.text_color=”green”
text.when_double_clicked=cambiacolore
app.display()
Usare i widget Tkinter assieme a guizero
I due tipi di widget possono essere usati assieme ed è possible anche usare i metodi tkinter nei widget guizero