Indice

Capitolo 11.
Interfacce Grafiche






   1. Interfacce Grafiche e Toolkits

Una Interfaccia Grafica è uno dei possibili sistemi con cui un utente può interagire con un programma. È basata su un sistema di oggetti chiamati Widget che raggruppati formano un ToolKit. Su piattaforme UNIX avete un'ampia scelta fra Motif, Athena, FLTK, LibForm, OpenLook, Tk e di recente Gtk.

     Motif è il toolkit storico di UNIX (o almeno quello più usato da un pezzo a questa parte, prima si usavano le librerie Athena). Tk deriva da Tcl, un altro linguaggio interpretato. Gtk invece è il più recente; è nato per sviluppare
The Gimp, uno splendido programma di manipolazione grafica, passato a Motif dopo che le limitazioni imposte da questo hanno cominciato a limitare lo sviluppo di Gimp.

     Gtk è successivamente assurto a toolkit per lo sviluppo di un completo Desktop chiamato Gnome e di una numerosa serie di altri programmi che sono in parte poi stati portati per avvalersi delle funzionalità offerte da Gnome stesso.

     Perl support nativamente Tk. Tuttavia non tratteremo questo toolkit in quanto è limitato in molte direzioni. In effetti è nato non per provvedere un complesso toolkit ma un toolkit veloce e piccolo adatto a piccole interfaccie. Ci occuperemo invece di Gtk.

     Il primo motivo stà nel fatto che Perl sfrutta completamente Gtk, permettendo di avere accesso a tutti i suoi widget e con la possibilità di dialogare anche con Gnome.

     Il secondo motivo è che avvalendosi di un Interface Builder chiamato glade risulta particolarmente rapida la stesura dell'interfaccia grafica. Il programma glade2perl si occupa di produrre il codice Perl che costruisce l'interfaccia per voi. A questo punto non vi resta che costruire il sistema di handler che gestiscono il verificarsi degli eventi.

     Ah, già: cosa sono gli eventi?


   2. Eventi

Un Evento è un qualsiasi tipo di azione che l'utente compie sull'interfaccia. Ad esempio la pressione di un pulsante È un evento. La selezione di un elemento in una lista di elementi È un evento. La discesa di un menù o la selezione di uno delle sue voci È un evento.

     Con Gtk e glade risulta particolarmente semplice la scrittura di complessi programmi. Ho personalmente sviluppato in meno di un'ora l'intera interfaccia di un tool di gestione di account e gruppi per Server UNIX, comprensiva di dialog per l'inserimento di dati utente, modifica di un gruppo e quant'altro, senza escludere una simpatica finestra 'About'! ;-)

     Ora pero' non esageriamo e partiamo dai fondamentali. Usiamo i widget di base di Gtk e cominciamo a fare qualcosa.


   
3. Una prima interfaccia

Costruiamo un semplice script che apra una finestra:


Solo una finestra Fig. 1
 
    1:  #!/usr/bin/perl
    2: 
    3:  #
    4:  # Importiamo il modulo Gtk
    5:  #
    6:  use Gtk;
    7: 
    8:  #
    9:  # Questa chiamata inizializza il modulo
   10:  #
   11:  init Gtk;
   12: 
   13:  #
   14:  # $win contiene il reference all'oggetto finestra
   15:  # appena creato
   16:  #
   17:  my $win = new Gtk::Window('toplevel');
   18: 
   19:  #
   20:  # Mostriamo la finestra
   21:  #
   22:  $win->show();
   23: 
   24:  #
   25:  # Facciamo partire il gestore (loop) degli eventi
   26:  # [ senza questa chiamata il programma aprirebbe la
   27:  # finestra e uscirebbe subito ]
   28:  #
   29:  main Gtk;
 

Ecco l'output del programma:

Come promesso apre una finestra (e solo quella!!!!) e si pone in attesa del verificarsi di qualche evento.

     Aggiungiamo qualche giocattolo alla nostra finestra, ad esempio un bottone con una scritta che consenta di terminare il programma:


Aggiungiamo un pulsante Fig. 2
 
    1:  #!/usr/bin/perl
    2: 
    3:  use Gtk;
    4: 
    5:  init Gtk;
    6: 
    7:  my $win = new Gtk::Window('toplevel');
    8:  $win->show();
    9: 
   10:  #
   11:  # Queste quattro righe creano il bottone con laber 'Quit'
   12:  # collegano alla sua pressione (un evento, dunque) la chiamata
   13:  # alla sub anonima che chiude la finestra principale ed esce,
   14:  # lo posizionano nella finestra e chiedono alla finestra di 
   15:  # mostrare tutti i suoi widget [ ->show_all() ];
   16:  #
   17:  my $button = new Gtk::Button('Quit');
   18:  $button->signal_connect('clicked', sub { $win->destroy(); exit; });
   19:  $win->add( $button );
   20:  $win->show_all();
   21: 
   22:  main Gtk;
 



Premendo il pulsante (che occupa tutta la finestra) viene prima chiusa la finestra e poi terminato il programma con un exit.


   
4. Containers

Per aggiungere un successivo bottone non sarà sufficiente chiamare nuovamente il metodo add() della finestra. Occorre aggiungere alla finestra principale un container. Si tratta di meta widget (ossia di widget che esistono, non si vedono direttamente ma se ne vedono gli effetti) il cui scopo è stabilire un ordine, un criterio con il quale posizionare i widget nella finestra o dentro altri widget.

     I due più semplici (e che fanno proprio al caso nostro) sono i Box. Ne esistono due tipi: verticale e orizzontale. Proviamo ad usare un container verticale, contenente una entry ossia un riquadro che contenga testo, olte al pulsante per uscire:


Un bottone ed una entry Fig. 3
 
    1:  #!/usr/bin/perl
    2: 
    3:  use Gtk;
    4: 
    5:  init Gtk;
    6: 
    7:  my $win = new Gtk::Window('toplevel');
    8: 
    9:  #
   10:  # Creiamo il notro container verticale
   11:  #
   12:  my $vbox = new Gtk::VBox();
   13:  $win->add($vbox);
   14: 
   15:  #
   16:  # Creiamo la entry e la posizioniamo nel VBox
   17:  # [ i tre parametri che seguono sono 
   18:  #   expand => puo' espandere oltre i suoi limiti?
   19:  #   fill => se espande puo' riempire lo spazio?
   20:  #   padding => quanti pixel ha intorno?
   21:  # ]
   22:  #
   23:  my $entry = new Gtk::Entry();
   24:  $vbox->pack_start( $entry, 0,0,0 );
   25:  $entry->set_text('Questo widget contiene testo');
   26: 
   27:  my $button = new Gtk::Button('Quit');
   28:  $button->signal_connect('clicked', sub { $win->destroy(); exit; });
   29: 
   30:  $vbox->pack_start( $button, 0,0,0 );
   31:  $win->show_all();
   32: 
   33:  main Gtk;
 






   
5. Un ultimo esempio

I commenti al codice dovrebbero essere sufficienti a questo punto per capire cosa faccia il programma.


Una finestra un po' piu' complessa Fig. 4
 
    1:  #!/usr/bin/perl
    2: 
    3:  #
    4:  # Include il supporto per Gtk
    5:  #
    6:  use Gtk;
    7: 
    8:  #
    9:  # Inizializza Gtk
   10:  #
   11:  init Gtk;
   12: 
   13:  #
   14:  # Crea la finestra e la dimensiona
   15:  #
   16:  my $win = new Gtk::Window('toplevel');
   17:  $win->height(300);
   18:  $win->width(300);
   19: 
   20:  #
   21:  # Il box che sviluppa in verticale
   22:  #
   23:  my $vbox = new Gtk::VBox();
   24:  $win->add($vbox);
   25: 
   26:  #
   27:  # La finestra scrollante che contiene
   28:  # il riquadro del testo
   29:  #
   30:  my $sw = new Gtk::ScrolledWindow();
   31:  $vbox->pack_start( $sw, 1,1,0 );
   32: 
   33:  #
   34:  # Il counter dei caratteri
   35:  #
   36:  my $cchar = 0;
   37: 
   38:  #
   39:  # Crea il riquadro per il testo
   40:  #
   41:  my $text = new Gtk::Text();
   42:  $sw->add( $text );
   43:  $text->insert(undef,undef,undef,"Questo e' un riquadro per l'inserimento del testo");
   44:  $text->set_editable(1); # Accetta input nel riquadro del testo
   45: 
   46:  #
   47:  # Il box orizzontale che contiene i bottoni
   48:  # a piede di pagina
   49:  #
   50:  my $hbox = new Gtk::HBox();
   51:  $vbox->pack_start( $hbox, 0,0,0 );
   52: 
   53:  #
   54:  # Una lable esplicativa
   55:  #
   56:  my $label = new Gtk::Label('Hai inserito');
   57:  $hbox->pack_start($label, 0,0,0 );
   58: 
   59:  #
   60:  # La entry del testo che conta i caratteri inseriti
   61:  #
   62:  my $charcount = new Gtk::Entry();
   63:  $hbox->pack_start( $charcount, 1,1,0 );
   64: 
   65:  #
   66:  # I due bottoni...
   67:  #
   68:  my $quit = new Gtk::Button('Quit');
   69:  $quit->signal_connect('clicked', sub { $win->destroy(); exit; });
   70: 
   71:  my $clear = new Gtk::Button('Cancella 10 caratteri');
   72:  $clear->signal_connect('clicked', sub { $text->set_point( 0 ); $text->forward_delete(10); });
   73: 
   74:  #
   75:  # Include i due bottoni
   76:  #
   77:  $hbox->pack_end( $quit, 0,0,0 );
   78:  $hbox->pack_end( $clear, 0,0,0 );
   79: 
   80:  #
   81:  # Chiede alla finestra principale di mostrare
   82:  # tutti i widget in essa contenuti
   83:  #
   84:  $win->show_all();
   85: 
   86:  #
   87:  # Collega un handler all'inserimento del testo
   88:  #
   89:  $text->signal_connect('changed', sub { $cchar++; $charcount->set_text($cchar); } );
   90: 
   91:  #
   92:  # Attiva il gestore degli eventi
   93:  #
   94:  main Gtk;
 

Eccone l'output:





Inizio Capitolo Indice