djechelon
09-07-2006, 04:21 AM
Ciao a tutti,
di questi tempi sto imparando a familiarizzare con Flex 2, e ho pensato bene di aiutare chi come me è stato al punto di partenza a prendere un po' di dimestichezza con la piattaforma.
Questo è un tutorial per niubbi, che io solitamente definisco donkey-proof. Il termine non è un'offesa, ma indica che è consigliato per coloro che non hanno alcuna conoscenza della piattaforma e/o dei linguaggi utilizzati e che vogliono imparare da zero. Se sapete già usare Flex smammate :D
Oggi vedremo come richiamare un controllo Flex da un'altro controllo, e come far sì che i controlli siano scalabili e riutilizzabili. Costruiremo una finestra popup personalizzata nel titolo. Sebbene Flex disponga già di un popup, con questo esercizio scopriremo i meccanismi del modello a oggetti di Flex.
Chi ha dimestichezza con linguaggi OO come Java e VB.NET scoprirà che Flex, grazie ad ActionScript 3.0, permette di gestire gli oggetti in maniera simile a ciò che i programmatori VB fanno con le Windows Form, ossia le applicazioni per Windows in finestra. Alla fine del tutorial vedremo come questo popup realizzato si potrà evolvere in qualcosa di più complesso e versatile. Il codice sarà commentato in quasi ogni riga per permettere ai neofiti di comprendere le dinamiche della programmazione a oggetti.
Unici requisiti per questo tutorial sono la conoscenza, anche per sentito dire, delle definizioni di classe, oggetto, proprietà e metodo, e un minimo di manualità con l'ambiente Flex 2 (creare progetti, inserire controlli drag and drop e impostarne le proprietà).
Cominciamo con una piccola premessa, utile a chiunque muove i primi passi nella programmazione: il principio fondamentale di ogni sviluppatore di buon software è la riusabilità. Dobbiamo fare il possibile per scrivere quanto meno codice possiamo e creare quanti meno componenti. Ho quindi pensato che una buona applicazione debba avere delle finestre di dialogo versatili, in grado di comunicare con l'utente cose come il verificarsi di un errore, ed eventualmente ottenere una risposta. Per ora limitiamoci ad un Popup che si piazza al centro della scena e sparisce col tasto OK. In seguito vedremo come, a partire dal popup semplice, sarà facile realizzare finestre interattive (tipo scelta SI/NO).
Cominciamo con lo stabilire il comportamento e l'utilizzo del nostro componente.
Intendo chiamarlo con una funzione ActionScript OpenPopup, che accetta due parametri di tipo Stringa, il primo relativo al testo del popup, il secondo, opzionale, relativo al titolo della finestra (cosa che il popup standard di Flex non permette di personalizzare). Dunque se voglio informare l'utente su un errore critico, chiamerò (vedremo dove) questa funzione:
OpenPopup('Si è verificato un grave errore nel file','Errore')
Quando il popup appare, l'intero movieclip viene bloccato e sfocato.
Cliccando su OK il popup scompare e il controllo torna al movie.
Costruiamo allora il controllo PopUp servendoci di MXML (si può fare in AS ma così impariamo anche un po' di MXML).
Creato il nostro progetto, creiamo un controllo e chiamiamolo esattamente PopUp. Il file ottenuto si chiamerà PopUp.mxml.
Dunque, abbiamo detto che ci serve una finestra con un titolo, un messaggio e un bottone. In area disegno definiamo i parametri dimensionali dell'applicazione. Trasciniamo un Panel e facciamo in modo che occupi tutto lo spazio, quindi trasciniamo un controllo TextArea nello stage, facendo in modo di renderlo il più grande possibile. Perchè TextArea? Perchè se usate un controllo label sarà molto probabile che vi imbattiate nelle scrollbar in caso di messaggi lunghi. Non importa che settiate l'andata a capo, perchè la label va a capo solo quando trova il carattere di andata a capo (per chi volesse saperlo si tratta della sequenza \r\n sotto Windows e del solo \n sotto Linux, ma mi pare che Flex tenga conto solo di \n).
Infine completiamo il design piazzando un bottone in basso e settandogli come etichetta la stringa "OK", o altra se preferite. Se inserirete un'etichetta tipo "Ciucciati il calzino" allora nessuno potrà contestarvi il non aver usato il popup standard di Flex :D
Adesso la parte un pochino più complicata: rendiamo interattivo il nostro controllo. La TextArea di cui sopra dovrà visualizzare un messaggio e nel Panel dovrà comparire un titolo. Vi ricordo che i titoli dei Panel sono le loro label.
Dato che dovremo accettare dei parametri, è opportuno definire ulteriori proprietà al nostro controllo. Questo che sto per fare si può fare in più modi: ho preferito MXML per lasciare ActionScript a dopo, ma i più smanettoni sapranno cosa scrivere nel nodo <mx:Script>.
Entriamo in layout Codice e inseriamo allora due stringhe, facendo attenzione agli ID che assegnamo loro. Sotto il nodo Panel
<mx:String id="content">No text defined!!!</mx:String>
<mx:String id="header">PopUp</mx:String>
Il popup, se non verrà indicato il titolo, visualizzerà la stringa PopUp, mentre se non è definito il testo mostrerà un errore (in inglese è ganzo ma potete tradurlo). Ricordate sempre di definire dei valori di default come ho fatto io, perchè non si può mai sapere...
Ora dobbiamo fare in modo che queste stringhe, di fatto proprietà della classe che stiamo realizzando, vengano mostrate al loro posto. Sempre nel codice, guardiamo nel nodo <mx:Panel> e, prima del simbolo di maggiore, inseriamo una proprietà:
title="{header}"
Cosa fa questo codice? All'atto dell'inizializzazione del controllo, durante l'esecuzione del costruttore, la proprietà title del pannello assume il valore specificato. Le parentesi graffe servono ad indicare che non stiamo parlando della stringa header, ma della variabile header, variabile che nello specifico è una proprietà della nostra classe. Facciamo la stessa cosa con la TextArea:
text="{content}"
Adesso la parte più difficile: il comportamento del bottone. Apparentemente direste che non è affatto difficile, perchè si risolve con una sola linea di codice, ma in realtà capire il meccanismo richiede un'ottima conoscenza del modello a oggetti, e io sono qui per spiegarlo brevemente.
Uno dei dettagli che non ho specificato in fase di progetto, e che prende piede adesso, è il fatto che il popup, in quanto generato dal controllo che chiama la funzione, è un figlio di tale controllo. Cerchiamo di capirci meglio.
Se ora state usando Mozilla Firefox, come me, potete aprire una nuova tab con la combinazione CTRL-T. La tab di navigazione è un'oggetto, ovviamente, ed è stata creata dalla finestra principale del browser, anch'essa un oggetto ovviamente. Questi due oggetti sono in rapporto di parentela, e hanno la possibilità di interagire direttamente. Quando digitate un URL nella barra, il campo URL chiede alla finestra principale di caricare il sito; la finestra, dunque, chiede alla tab di visualizzare il sito su schermo. Quando fate click su un link, la tab chiede alla finestra principale di cambiare pagina e così via.
La stessa regola si applica ai controlli Flex.
All'apparenza, alla chiusura del popup, potremmo semplicemente volerlo nascondere: purtroppo questa pratica, diffusissima tra gli sviluppatori, causa uno spreco eccessivo di memoria, e nello specifico può causare problemi alla visualizzazione della pagina. In poche parole il popup va eliminato.
Fatta questa lunga premessa diamo uno sguardo al codice da inserire, commentandolo. Nel nodo <mx:Button> andiamo a definire un handler per l'evento click. Per chi non avesse capito il significato di questa mia affermazione, sappiate che ciò che ho detto significa stabilire cosa il bottone deve fare quando è cliccato. Inseriamo il seguente codice come sopra:
click="this.parent.removeChild(this)"
In ogni oggetto c'è sempre un riferimento al padre, cioè all'oggetto che ha generato il figlio. Guardando nella documentazione di Flex, osserviamo che ogni oggetto Flex ha, tra le tante cose, un metodo removeChild che distrugge un figlio. Questo metodo è sovraccaricato, in quanto accetta sia un ID numerico che il figlio da rimuovere in formato oggetto. Fortunatamente possiamo usare la seconda chiamata, in quando ottenere l'ID numerico del nostro controllo è un po' un problema. Ma chi è ovviamente il figlio di un padre se non sè stesso? Scusate il gioco di parole, ma è ovvio che il popup deve autodistruggersi, quindi passa sè stesso sotto forma dell'oggetto this. Questo strano personaggio, in tutti i linguaggi OOP, rappresenta l'oggetto stesso, teniatelo a mente.
Abbiamo finito il popup. Il codice risultante sarà di questo tipo:
<?xml version="1.0" encoding="utf-8"?>
<mx:Panel xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="300" height="350"
title="{header}" horizontalAlign="center" verticalAlign="middle"
creationCompleteEffect="myShow" removedEffect="myHide" >
<mx:Sequence id="myShow">
<mx:Resize duration="1500" heightBy="0" heightTo="0" widthBy="0" widthTo="300" />
<mx:Resize startDelay="500" duration="1500" heightTo="350" />
</mx:Sequence>
<mx:Parallel id="myHide" />
<mx:String id="content">No text defined!!!</mx:String>
<mx:String id="header">PopUp</mx:String>
<mx:TextArea id="poptxt" fontFamily="Verdana" right="10" left="10" top="10" bottom="76" text="{content}" textAlign="center"/>
<mx:Button id="btn" label="OK" horizontalCenter="-0.5" bottom="10" labelPlacement="bottom" enabled="true" click="this.parent.removeChild(this)" showEffect="Alpha"/>
</mx:Panel>
[TAGLIATO PER ECCESSIVA LUNGHEZZA... CONTINUA IN REPLY]
di questi tempi sto imparando a familiarizzare con Flex 2, e ho pensato bene di aiutare chi come me è stato al punto di partenza a prendere un po' di dimestichezza con la piattaforma.
Questo è un tutorial per niubbi, che io solitamente definisco donkey-proof. Il termine non è un'offesa, ma indica che è consigliato per coloro che non hanno alcuna conoscenza della piattaforma e/o dei linguaggi utilizzati e che vogliono imparare da zero. Se sapete già usare Flex smammate :D
Oggi vedremo come richiamare un controllo Flex da un'altro controllo, e come far sì che i controlli siano scalabili e riutilizzabili. Costruiremo una finestra popup personalizzata nel titolo. Sebbene Flex disponga già di un popup, con questo esercizio scopriremo i meccanismi del modello a oggetti di Flex.
Chi ha dimestichezza con linguaggi OO come Java e VB.NET scoprirà che Flex, grazie ad ActionScript 3.0, permette di gestire gli oggetti in maniera simile a ciò che i programmatori VB fanno con le Windows Form, ossia le applicazioni per Windows in finestra. Alla fine del tutorial vedremo come questo popup realizzato si potrà evolvere in qualcosa di più complesso e versatile. Il codice sarà commentato in quasi ogni riga per permettere ai neofiti di comprendere le dinamiche della programmazione a oggetti.
Unici requisiti per questo tutorial sono la conoscenza, anche per sentito dire, delle definizioni di classe, oggetto, proprietà e metodo, e un minimo di manualità con l'ambiente Flex 2 (creare progetti, inserire controlli drag and drop e impostarne le proprietà).
Cominciamo con una piccola premessa, utile a chiunque muove i primi passi nella programmazione: il principio fondamentale di ogni sviluppatore di buon software è la riusabilità. Dobbiamo fare il possibile per scrivere quanto meno codice possiamo e creare quanti meno componenti. Ho quindi pensato che una buona applicazione debba avere delle finestre di dialogo versatili, in grado di comunicare con l'utente cose come il verificarsi di un errore, ed eventualmente ottenere una risposta. Per ora limitiamoci ad un Popup che si piazza al centro della scena e sparisce col tasto OK. In seguito vedremo come, a partire dal popup semplice, sarà facile realizzare finestre interattive (tipo scelta SI/NO).
Cominciamo con lo stabilire il comportamento e l'utilizzo del nostro componente.
Intendo chiamarlo con una funzione ActionScript OpenPopup, che accetta due parametri di tipo Stringa, il primo relativo al testo del popup, il secondo, opzionale, relativo al titolo della finestra (cosa che il popup standard di Flex non permette di personalizzare). Dunque se voglio informare l'utente su un errore critico, chiamerò (vedremo dove) questa funzione:
OpenPopup('Si è verificato un grave errore nel file','Errore')
Quando il popup appare, l'intero movieclip viene bloccato e sfocato.
Cliccando su OK il popup scompare e il controllo torna al movie.
Costruiamo allora il controllo PopUp servendoci di MXML (si può fare in AS ma così impariamo anche un po' di MXML).
Creato il nostro progetto, creiamo un controllo e chiamiamolo esattamente PopUp. Il file ottenuto si chiamerà PopUp.mxml.
Dunque, abbiamo detto che ci serve una finestra con un titolo, un messaggio e un bottone. In area disegno definiamo i parametri dimensionali dell'applicazione. Trasciniamo un Panel e facciamo in modo che occupi tutto lo spazio, quindi trasciniamo un controllo TextArea nello stage, facendo in modo di renderlo il più grande possibile. Perchè TextArea? Perchè se usate un controllo label sarà molto probabile che vi imbattiate nelle scrollbar in caso di messaggi lunghi. Non importa che settiate l'andata a capo, perchè la label va a capo solo quando trova il carattere di andata a capo (per chi volesse saperlo si tratta della sequenza \r\n sotto Windows e del solo \n sotto Linux, ma mi pare che Flex tenga conto solo di \n).
Infine completiamo il design piazzando un bottone in basso e settandogli come etichetta la stringa "OK", o altra se preferite. Se inserirete un'etichetta tipo "Ciucciati il calzino" allora nessuno potrà contestarvi il non aver usato il popup standard di Flex :D
Adesso la parte un pochino più complicata: rendiamo interattivo il nostro controllo. La TextArea di cui sopra dovrà visualizzare un messaggio e nel Panel dovrà comparire un titolo. Vi ricordo che i titoli dei Panel sono le loro label.
Dato che dovremo accettare dei parametri, è opportuno definire ulteriori proprietà al nostro controllo. Questo che sto per fare si può fare in più modi: ho preferito MXML per lasciare ActionScript a dopo, ma i più smanettoni sapranno cosa scrivere nel nodo <mx:Script>.
Entriamo in layout Codice e inseriamo allora due stringhe, facendo attenzione agli ID che assegnamo loro. Sotto il nodo Panel
<mx:String id="content">No text defined!!!</mx:String>
<mx:String id="header">PopUp</mx:String>
Il popup, se non verrà indicato il titolo, visualizzerà la stringa PopUp, mentre se non è definito il testo mostrerà un errore (in inglese è ganzo ma potete tradurlo). Ricordate sempre di definire dei valori di default come ho fatto io, perchè non si può mai sapere...
Ora dobbiamo fare in modo che queste stringhe, di fatto proprietà della classe che stiamo realizzando, vengano mostrate al loro posto. Sempre nel codice, guardiamo nel nodo <mx:Panel> e, prima del simbolo di maggiore, inseriamo una proprietà:
title="{header}"
Cosa fa questo codice? All'atto dell'inizializzazione del controllo, durante l'esecuzione del costruttore, la proprietà title del pannello assume il valore specificato. Le parentesi graffe servono ad indicare che non stiamo parlando della stringa header, ma della variabile header, variabile che nello specifico è una proprietà della nostra classe. Facciamo la stessa cosa con la TextArea:
text="{content}"
Adesso la parte più difficile: il comportamento del bottone. Apparentemente direste che non è affatto difficile, perchè si risolve con una sola linea di codice, ma in realtà capire il meccanismo richiede un'ottima conoscenza del modello a oggetti, e io sono qui per spiegarlo brevemente.
Uno dei dettagli che non ho specificato in fase di progetto, e che prende piede adesso, è il fatto che il popup, in quanto generato dal controllo che chiama la funzione, è un figlio di tale controllo. Cerchiamo di capirci meglio.
Se ora state usando Mozilla Firefox, come me, potete aprire una nuova tab con la combinazione CTRL-T. La tab di navigazione è un'oggetto, ovviamente, ed è stata creata dalla finestra principale del browser, anch'essa un oggetto ovviamente. Questi due oggetti sono in rapporto di parentela, e hanno la possibilità di interagire direttamente. Quando digitate un URL nella barra, il campo URL chiede alla finestra principale di caricare il sito; la finestra, dunque, chiede alla tab di visualizzare il sito su schermo. Quando fate click su un link, la tab chiede alla finestra principale di cambiare pagina e così via.
La stessa regola si applica ai controlli Flex.
All'apparenza, alla chiusura del popup, potremmo semplicemente volerlo nascondere: purtroppo questa pratica, diffusissima tra gli sviluppatori, causa uno spreco eccessivo di memoria, e nello specifico può causare problemi alla visualizzazione della pagina. In poche parole il popup va eliminato.
Fatta questa lunga premessa diamo uno sguardo al codice da inserire, commentandolo. Nel nodo <mx:Button> andiamo a definire un handler per l'evento click. Per chi non avesse capito il significato di questa mia affermazione, sappiate che ciò che ho detto significa stabilire cosa il bottone deve fare quando è cliccato. Inseriamo il seguente codice come sopra:
click="this.parent.removeChild(this)"
In ogni oggetto c'è sempre un riferimento al padre, cioè all'oggetto che ha generato il figlio. Guardando nella documentazione di Flex, osserviamo che ogni oggetto Flex ha, tra le tante cose, un metodo removeChild che distrugge un figlio. Questo metodo è sovraccaricato, in quanto accetta sia un ID numerico che il figlio da rimuovere in formato oggetto. Fortunatamente possiamo usare la seconda chiamata, in quando ottenere l'ID numerico del nostro controllo è un po' un problema. Ma chi è ovviamente il figlio di un padre se non sè stesso? Scusate il gioco di parole, ma è ovvio che il popup deve autodistruggersi, quindi passa sè stesso sotto forma dell'oggetto this. Questo strano personaggio, in tutti i linguaggi OOP, rappresenta l'oggetto stesso, teniatelo a mente.
Abbiamo finito il popup. Il codice risultante sarà di questo tipo:
<?xml version="1.0" encoding="utf-8"?>
<mx:Panel xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="300" height="350"
title="{header}" horizontalAlign="center" verticalAlign="middle"
creationCompleteEffect="myShow" removedEffect="myHide" >
<mx:Sequence id="myShow">
<mx:Resize duration="1500" heightBy="0" heightTo="0" widthBy="0" widthTo="300" />
<mx:Resize startDelay="500" duration="1500" heightTo="350" />
</mx:Sequence>
<mx:Parallel id="myHide" />
<mx:String id="content">No text defined!!!</mx:String>
<mx:String id="header">PopUp</mx:String>
<mx:TextArea id="poptxt" fontFamily="Verdana" right="10" left="10" top="10" bottom="76" text="{content}" textAlign="center"/>
<mx:Button id="btn" label="OK" horizontalCenter="-0.5" bottom="10" labelPlacement="bottom" enabled="true" click="this.parent.removeChild(this)" showEffect="Alpha"/>
</mx:Panel>
[TAGLIATO PER ECCESSIVA LUNGHEZZA... CONTINUA IN REPLY]