Stampa  |  Nascondi immagini  |  Mostra immagini

GUI


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:

figura

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.
figura

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:

figura

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.



Versione originale: http://programmazione.html.it/guide/lezione/1302/gui/

© 1997-2006 HTML.it
La vendita, il noleggio, il prestito e la diffusione del contenuto di questa pagina sono vietate, tranne nei casi specificati nella pagina http://www.html.it/info/note-legali.php