Nota: in un'altra accezione (che vedremo piu' avanti) anche le icone sono finestre.
Finestra ha:
Nota: le finestre intese in questa accezione sono anche chiamate "finestre top-level". In un'altra accezione per finestra si intende qualsiasi area rettangolare dello schermo con caratteristiche di comportamento proprie (quindi anche i vari elementi dentro una finestra sono finestre (ma lo vedremo piu' avanti).
C'e' l'interfaccia di una particolare applicazione e l'interfaccia generale dell'ambiente di lavoro su una certa macchina, cioe' l'interfaccia del sistema. Qui parliamo del primo caso.
Una interfaccia utente grafica e' costituita da:
Alcuni usano il termine componenti di interfaccia per indicare sia le finestre che i dispositivi, altri solo per i dispositivi.
Oggetti con aspetto grafico e comportamento (sensibilita' a particolari eventi e capacita' reattive) che "popolano" una finestra e permettono interazione con l'utente.
Sono forniti da una libreria o toolkit per sviluppo di interfacce: pacchetto che fornisce insieme di elementi di interfaccia pronti all'uso e insieme di funzioni (API) per utilizzarli nella costruzione di un'interfaccia.
La libreria fornisce tipi o classi di dispositivi. Ciascun tipo ha proprie caratteristiche di aspetto / comportamento (es. bottoni, campi di input testuale...) in parte personalizzabili, e possibilita' di inserire comportamenti aggiuntivi.
Esempio: un bottone e' un'area rettangolare sensibile al click del mouse. Posso personalizzarlo scegliendo dimensioni, colore, font della scritta... Ha predefinito il comportamento di evidenziarsi quando viene cliccato, posso aggiungere quello di chiamare una certa funzione applicativa (es. salvare il file corrente).
La libreria / toolkit fornisce:
Il comportamento di un programma dotato di interfaccia utente grafica e' di tipo inter-attivo.
Sono le azioni compiute dell'utente sui dispositivi di input
a determinare il flusso di esecuzione del programma.
Contrariamente ai programmi batch in cui il flusso e' predefinito
nel codice.
Compito dell'interfaccia e' raccogliere le azioni e scatenare
le reazioni corrispondenti.
+------+ azione su +------------+ | |--(1)--> dispositivo --(2)--> evento --->| (3) | | | di input |interfaccia | |utente| |della | | | feedback su reazione |applicazione| | |<--(5)-- dispositivi <--(4)-- (cambio <---| | +------+ di output di stato) +------------+
(1) L'utente compie azioni sui dispositivi di input (mouse, tastiera).
(2) Le azioni sono tradotte in eventi. Evento = pacchetto di informazioni che descrivono che cosa e' avvenuto. Qui la libreria / toolkit esegue gia' una parziale interpretazione delle azioni. Esempi:
(3) L'evento viene elaborato dal codice dell'interfaccia, per decidere che cosa fare (come reagire). L'elaborazione puo' avvenire a due livelli:
(4) La reazione (avvenuto cambio di stato) viene comunicata all'utente come feedback sui disposiviti di output (schermo, altoparlante).
(5) L'utente riceve il feedback e in base a questo decidera' la prossima azione...
Applicazione per cambiare il contrasto di una foto. L'interfaccia mostra la foto e un potenziometro o slider con cursore mobile.
Evento di aggancio / rilascio del cursore da parte dell'utente
(premendo / rilasciando il mouse sopra) e' gestito a livello libreria.
Evento di movimento del cursore (trascinandolo a mouse premuto)
e' gestito
Per associare comportamenti aggiuntivi ai dispositivi di interfaccia, le librerie / toolkit prevedono il meccanismo delle callback.
Callback = funzione "da chiamare in risposta" a un evento che accade su un certo componente di interfaccia.
Una callback e' una funzione scritta dal programmatore, il quale poi comunica alla libreria che dovra' chiamare questa funzione ogni volta che un certo tipo di evento si verifichera' su un certo componente di interfaccia. La funzione verra' poi chiamata automaticamente.
Al suo interno una funzione callback puo' accedere sia all'interfaccia (tramite le funzioni della API del toolkit), sia all'applicazione sottostante. Esempio: eseguire un calcolo applicativo e poi mostrare il risultato nell'interfaccia.
Programmatore scrive una funzione con parametri
conformi a quelli stabiliti dal toolkit
e poi la registra come callback.
Quando il toolkit chiamera' la callback
(a seguito del verificarsi dell'evento),
le passera' automaticamente i parametri prelevandoli dall'evento attuale.
Struttura del codice di un programma che implementa un'interfaccia utente (per una certa applicazione) facendo uso di un toolkit.
Vediamo le parti del programma (a livello di codice scritto dal programmatore) e che cosa succede dentro (a livello della libreria / toolkit).
Che cosa scrive il programmatore | Che cosa avviene nella libreria / toolkit | |
1. Dichiara che intende usare il toolkit | Direttiva include in C, import in java... | |
2. Inizializza il toolkit | Istruzione della API del toolkit. Certi toolkit (es. java) non richiedono inizializzazione esplicita. | Libreria si collega a librerie di piu' basso livello che le permetteranno di produrre grafica e catturare eventi (ved punto 3) |
3. Crea l'interfaccia (creare le finestre, i dispositivi, personalizzarne l'aspetto, posizionarli...) | Istruzioni della API del toolkit | Libreria costruisce la grafica e i comportamenti usando librerie di piu' basso livello fornite dal sistema operativo o comunque da strati software inferiore. |
4. Scrive le callback per implementare i comportamenti aggiuntivi (es. accedere all'applicazione sottostante) | Programmatore scrive una funzione con parametri e valore di ritorno conformi a quelli stabiliti dal toolkit per callback a quel tipo di evento in quel tipo di componente. | |
5. Registra le callback, cioe' associare le funzioni-comportamenti ai dispositivi | Istruzioni della API del toolkit per registrare la funzione come callback a quel componente per quel tipo di evento. | Libreria compila una tabella di associazioni dispositivo - evento - callback. |
6. Mostra a schermo l'interfaccia (almeno la finestra principale, mentre altre possono essere pensate per apparire a seguito di eventi) | Istruzioni della API del toolkit per rendere visibili le finestre | Libreria mappa finestre sullo schermo |
7. Fa partire il ciclo degli eventi, cioe' l'interazione con l'utente (azione - evento - reazione - feedback...) | Istruzione della API del toolkit. Certi toolkit (es. java) non hanno un'istruzione esplicita, il ciclo degli eventi parte automaticamente non appena viene mostrata una finestra. | Libreria esegue ciclo infinito in cui ad ogni giro:
|
Riguarda la gestione del ciclo degli eventi.
Interazione bloccante
Flusso del programma completamente guidato da eventi.
Finche' non arriva un evento, il programma dorme
(interazione bloccata) e non usa CPU.
Quando riceve un evento, allora si risveglia (riprende l'esecuzione)
per reagire all'evento.
Corrisponde allo schema appena visto.
Interazione non bloccante
Programma oltre a reagire agli eventi esegue anche operazioni autonome,
indipendenti dagli eventi (es: animazione).
Mentre attende che arrivino eventi, nel frattempo
esegue le sue operazioni (consumando CPU).
Se arriva un evento, allora interrompe la sua normale
attivita' per reagire all'evento.
Come si realizza l'interazione non bloccante?
Alcuni toolkit prevedono uno speciale evento nullo corrispondente ad assenza di eventi. A questo posso associare una callback, chiamata idle callback, che implementi l'operazione autonoma.
Altri toolkit (es. java) prevedono timer con cui posso scatenare un evento ogni tot di tempo. A questo evento "fittizio" posso associare una callback che implementi l'operazione autonoma.
I dispositivi forniti da una libreria / toolkit sono elementi di interfaccia pronti all'uso (bottoni, menu'...).
Si classificano in diversi tipi o classi, ciascun tipo con certe caratteristiche di aspetto / comportamento.
Elementi attivi (sensibili a input). Esempi:
Elementi inerti (solo aspetto grafico). Esempi:
Aree dedicate a scopi speciali: aree grafiche, aree per visualizzazione o editing di testi...
Dal punto di vista dell'utente dell'interfaccia un dispositivo / componente di interfaccia e' caratterizzato da:
Dal punto di vista del programmatore un componente e' caratterizzato da:
Esempi:
Due categorie fondamentali di componenti:
Mediante i contenitori si struttura lo spazio della finestra definendo vincoli per la disposizione (layout) dei componenti al suo interno. Meccanismo a scatole cinesi (gerarchia di annidamento dei contenitori).
Esempio: la finestra e' divisa in due parti verticalmente, nella parte sinistra c'e' un'area di testo, la parte destra e' strutturata come una griglia 3 righe x 3 colonne con dentro dei bottoni.
+--------------------+----+----+----+ | | B1 | B2 | B3 | | +----+----+----+ | area di testo | B4 | B5 | B6 | | +----+----+----+ | | B7 | B8 | B9 | +--------------------+----+----+----+La gerarchia e':
contenitore a due scomparti verticali | +----------+----------+ | | area di testo contenitore a griglia 3x3 | +-----+-----+ | ... | bottone B1 ... bottone B9
Con contenitori posso raggruppare componenti concettualmente collegati, disegnare bordi e cornici.
In genere i componenti di un toolkit sono organizzati in classi
secondo la filosofia object oriented
(questo anche se il toolkit e' scritto in un linguaggio
non object-oriented).
C'e' una classe per ciascun tipo di componente fornito dal toolkit.
Creare un componente = creare un'istanza della classe opportuna.
Le azioni dell'utente sui dispositivi di input generano segnali che sono raccolti dal sistema operativo come eventi elementari (es. pressione di un tasto della tastiera, movimento del mouse, pressione di un tasto del mouse).
Il sistema operativo (o strati sw poco sopra esso) fornisce una
libreria di basso livello per accedere a questi eventi elementari.
La libreria / toolkit per interfacce utente usa questa libreria
di basso livello per accedere agli eventi elementari del sistema operativo
e costruire da questi i "suoi" eventi, che sono eventi a piu' alto
livello di astrazione.
Esempi:
Inoltre ci sono eventi del toolkit che non hanno controparte come eventi elementari perche' non generati da utente. Esempio: evento generato da timer (ved. interazione non bloccante).
Nota: chiusa la parentesi sugli eventi elementari, per "eventi" nel seguito intendiamo gli eventi del toolkit.
Quando su un componente di interfaccia avviene un evento, il toolkit lo puo' gestire come:
Bottone del tipo che si evidenzia quando l'utente ci passa sopra col mouse e scatta quando preme:
Campo testuale (per l'immissione di una stringa di testo):
"Slider" (barra di scorrimento per l'immissione di un
valore numerico in un certo intervallo):
Un toolkit puo' fornire un GUI Designer. Programma interattivo che permette la progettazione di interfacce grafiche basate su tale toolkit.
Il GUI Designer produce il codice relativo all'interfaccia.
Il programmatore deve solo riempire il corpo delle procedure callback associate ai componenti.