Arrivati a questo punto qualcuno potrebbe chiedersi se e' possibile,
con python, costruire quelle belle applicazioni, in ambiente window, con
l'interfaccia grafica, il menu, i bottoni e tutto il resto. Quello che
abbiamo imparato e' utile per costruire degli script da eseguire sulla
linea di comando, ma con python si puo' osare di piu'.
Sono stati implementati diversi moduli che permettono di aggiungere ad
un programma python una bella interfaccia grafica a finestre. In
particolare intendo introdurre qualche concetto in merito a 3
librerie:
- Tkinter: Un modulo che permette di interfacciare
python a X-Windows.
Infatti Tkinter utilizza il
linguaggio Tk, utilizzato da molti anni in ambiente
unix per sviluppare software in ambiente X-Windows. Questa libreria
deve essere utilizzata da coloro che intendono sviluppare interfacce
grafiche multipiattaforma, quindi programmi che devono girare sotto
unix, linux, windows e anche sotto Mac. Questa libreria ha il
vantaggio di essere gia' compresa nella installazione standard, quindi
non sono necessarie installazioni aggiuntive per iniziare a lavorare con
l'interfaccia grafica.
- Win32Extension: Una famiglia di moduli per
costruire interfacce grafiche in ambiente Microsoft
Windows.
Win32Extension e' una vasta raccolta di moduli,
scritti da Mark Hammond, che permettono di utilizzare le API Win 32 di
windows e le MFC (Microsoft Foundation Class). Questa libreria deve
essere utilizzata da coloro che sono interessati a lavorare
esclusivamente in ambiente windows, infatti in tal caso si possono
sfruttare tutte le potenzialita' di windows. Io ho trovato
problematica la ricerca di documentazione in rete, ma se qualcuno e'
veramente interessato puo' acquistare il libro dell'autore della
libreria, che e' il riferimento assoluto (O'Reilly book Python
Programming on Win32 (http://www.ora.com/catalog/pythonwin32/)).
- WxPython: Una libreria che permette di creare delle
interfacce grafiche portabili su diverse piattaforme. WxPython e' basata
sulla libreria WxWindows, la quale implementa l'intera struttura in C++.
Attualmente WxWindows (e di conseguenza WxPython) supporta MS Windows
(16-bit, Windows 95 and Windows NT), Unix con GTK+, Unix con Motif, e
Mac.
Questa libreria e' simile a Tkinter, ma molto piu' moderna e
potente. L'intera libreria e tutte le informazioni presso il sito
ufficiale (www.wxpython.org (http://www.wxpython.org)).
Di seguito vi propongo esempi nelle tre diverse librerie:
Per utilizzare Tkinter e' necessario compiere le seguenti
operazioni:
- Importare il modulo chiamato (in modo originale) "Tkinter".
- Inizializzare l'ambiente grafico richiamando la funzione "Tk()".
- Ogni finestra grafica deve essere creata partendo da un oggetto base
chiamato "Frame". Il frame e' un contenitore di altri oggetti grafici
(che in Tk vengono chiamati "Widgets").
- Dopo aver creato il frame, dobbiamo creare tutti i widgets contenuti
in esso, nel nostro esempio tre bottoni e una casella di testo.
- Una volta definito l'aspetto grafico della applicazione, si deve
richiamare la funzione mainloop() incaricata di far
partire il programma e di rimanere in attesa di input dall'utente.
L'input dell'utente proviene dalla azione che egli effettua con il mouse
sui widgets.
Vediamo il listato completo del programma:
from Tkinter import * # importo il modulo # costruisco
una mia classe che gestisce la finestra class Application(Frame): #
metodo che scrive un messaggio a video def
scrivi_messaggio(self): self.mess["text"] = "Ciao a tutti!", #
metodo che pulisce il messaggio a video def
cancella_messaggio(self): self.mess["text"] = "", # metodo
costruttore che crea gli oggetti grafici def __init__(self,
master=None): f = Frame(master) f.pack() # crea il bottone di
uscita (di colore rosso) self.esci = Button(f) self.esci["text"] =
"QUIT" self.esci["fg"] = "red" self.esci["command"] =
f.quit self.esci.pack({"side": "left"}) # crea il bottone che
permette di scrivere il messaggio self.butt_mess =
Button(f) self.butt_mess["text"] =
"Scrivi", self.butt_mess["command"] =
self.scrivi_messaggio self.butt_mess.pack({"side": "left"}) # crea
il bottone che permette di pulire il messaggio self.butt_canc_mess =
Button(f) self.butt_canc_mess["text"] =
"Cancella", self.butt_canc_mess["command"] =
self.cancella_messaggio self.butt_canc_mess.pack({"side": "left"}) #
crea l'oggetto grafico che contiene il messaggio self.mess =
Message(f) self.mess["text"] = "", self.mess.pack({"side":
"left"})
# corpo principale del programma finestra = Tk() app
= Application(finestra) finestra.mainloop()
Ecco come si presenta graficamente la applicazione:
Ho cercato di commentare il codice in modo da far capire i vari
passaggi. Si puo' notare che ho programmato ad oggetti. Infatti ho
creato una classe, denominata "Applicazione", che contiene i dati e le
operazioni necessarie alla costruzione della interfaccia grafica. I
dati sono stati creati dinamicamente al momento della loro assegnazione e
sono i seguenti:
- L'oggetto "esci" che e' il bottone di uscita.
- L'oggetto "butt_mess" che e' il bottone che scrive il messaggio.
- L'oggetto "butt_canc_mess" che e' il bottone che cancella il
messaggio.
- L'oggetto "mess" che e' la zona grafica che contiene il messaggio.
Per tutti questi oggetti ho fatto 3 operazioni:
- ho creato una istanza,
- ho inizializzato alcuni dati membro che ne controllano l'aspetto
grafico e
- ho chiamato la funziona pack che li visualizza a
video.
Per quanto concerne i bottoni, il dato membro "command" richiede il
nome della funzione che risponde all'evento della pressione del tasto.
Infatti quando viene premuto il tasto "butt_mess" python invoca la
funzione denominata "scrivi_messaggio".
Il corpo principale del programma, in fondo al codice, non fa altro che
eseguire le tre operazioni principali che ho elencato precedentemente.
Chiaramente in questa sede e' impossibile esaminare tutto il modulo, il
quale e' ricco di oggetti grafici di ogni tipo. è possibile scaricare dal
sito di python un discreto manuale in inglese, chiamato Tkinter Life
Preserver (http://www.python.org/doc/life-preserver/index.html), con la
spiegazione di tutti gli oggetti.
Per utilizzare le librerie di Mark Hammond si deve conoscere il mondo
windows, e in particolare le Api Win32.
Quindi, anche in questo caso non
posso approfondire l'argomento, anche perche' sarebbe piu' vasto di quello
che si possa immaginare. Vi offro comunque un esempio con qualche piccola
spiegazione.
Il processo di creazione di una finestra in windows e' piuttosto
articolato, e' necessario svolgere i seguenti passi:
- Si deve creare una classe di appartenenza della finestra. Tale
classe definisce le funzionalita' della finestra, ad esempio quale
funzione e' responsabile della sua gestione. In windows infatti, per
ogni finestra grafica, esiste una funzione che gestisce completamente
tale finestra.
- Si deve registrare in windows la classe appena creata, in modo che
esso ne venga a conoscenza. Questa operazione in python si svolge
richiamando la funzione "win32ui.RegisterWndClass"
- Si deve creare l'oggetto finestra con tutte le sue caratteristiche
grafiche. Questa operazione in python si svolge richiamando la funzione
"CreateWindowEx"
- Si deve richiamare una funzione, denominata "ShowWindow", incaricata
di mostrare a video il risultato della finestra.
# importo tutti i moduli necessari import
win32con import win32ui from pywin.mfc import window, dialog,
thread, afxres
# classe che crea la finestra (eredita da
window.Wnd) class HelloWindow(window.Wnd): def __init__(self): #
creo un oggetto finestra window.Wnd.__init__(self,
win32ui.CreateWnd())
classe = win32ui.RegisterWndClass(0, 0,
win32con.COLOR_WINDOW + 1) zona = (100, 100, 400, 300) # dico a
windows di creare visivamente la finestra con tutte le sue
caratteristiche
self._obj_.CreateWindowEx(win32con.WS_EX_CLIENTEDGE,
classe,'Ciao a tutti!', win32con.WS_OVERLAPPEDWINDOW, zona, None,
0, None)
# classe che definisce la applicazione (eredita da
thread.WinApp) class HelloApp(thread.WinApp):
# metodo che
inizializza l'istanza grafica della applicazione def
InitInstance(self): self.frame =
HelloWindow() self.frame.ShowWindow(win32con.SW_SHOWNORMAL) # indica
a windows che si tratta della finestra principale della
applicazione
self.SetMainFrame(self.frame)
# corpo
principale del programma, istanzia la applicazione app =
HelloApp()
Osservando il codice si possono fare le seguenti osservazioni:
- è necessario importare un insieme di moduli che definiscono tutte le
classi di windows. Ad esempio il modulo "win32con" contiene tutte le
costanti utilizzate nelle Api Win32.
- Il corpo principale del programma richiama semplicemente una classe,
denominata "HelloApp", che gestisce la funzione responsabile della
finestra grafica.
- La classe "HelloApp" richiama automaticamente il metodo
"InitInstance". Tale richiamo e' contenuto nel costruttore della classe
"thread.WinApp". Infatti, utilizzando le MFC si deve programmare
solamente effettuando l'overloading dei metodi che si devono
personalizzare. In questo esempio la classe "HelloApp" ridefinisce il
metodo "InitInstance" al fine di indicare a windows di caricare la
nostra nuova finestra. Quindi il programmatore perde la classica
sequenzialita' delle operazioni e deve conoscere molto bene cio' che
avviene nelle classi madri da cui si deriva.
- nel metodo "InitInstance" vengono svolte tutte le operazioni,
compresa la creazione di un oggetto della classe "HelloWindow",
incaricata di definire le caratteristiche grafiche della finestra.

Questa applicazione e' veramente minimale, in quanto si limita a
mostrare una finestra vuota con il titolo "Ciao a tutti!"
Per utilizzare WxPython e' necessario compiere le seguenti
operazioni:
- Importare il modulo chiamato (in modo originale) "wxPython.wx".
- Creare una classe derivata da "WxApp", la quale rappresenta l'intera
applicazione. La classe "WxApp" gestisce il sistema dei messaggi e il
loop degli eventi.
- Nel metodo "OnInit" di WxApp e' necessario inizializzare
l'applicazione. In particolare creare il frame e mostrare la finestra.
Il frame rappresenta la finestra principale.
Vediamo il listato completo del programma:
from wxPython.wx import *
class MyApp(wxApp): #
derivo la classe applicazione def OnInit(self): frame =
wxFrame(NULL, -1, "Ciao da wxPython") #creo il frame frame.Show(true)
#mostro il frame return true
app = MyApp(0) # istanzio
l'applicazione app.MainLoop() # faccio partire il loop che gestisce gli
eventi
Ecco come si presenta graficamente la applicazione:
Anche in questo caso ho cercato di commentare il codice in modo da far
capire i vari passaggi. Si puo' notare che tutta la libreria e'
organizzata ad oggetti. Infatti ho derivato la classe applicazione e ne ho
personalizzato il comportamento. Il corpo principale del programma, in
fondo al codice, non fa altro che istanziare la classe applicazione e far
partire il loop che aspetta input dall'utente e gestisce gli
eventi. Anche in questo caso ho fatto un esempio semplicissimo, il
passo successivo sarebbe quello di creare dei controlli specifici
all'interno del frame. Ma rimando questo ai manuali di
WxPython. |