Home » ActionScript 3.0, Adobe, Flash AS 3

Estendere il componente ComboBox per caricare dati XML (AS 3.0 – Flash CS3/4)

15 January 2009 No Comment

Problema: popolare due o più ComboBox con contenuti acquisiti da diversi file XML.

Soluzione: estendere la classe ComboBox affinché abbia un nuovo metodo pubblico loadData(xmlPath:String) che accetta come parametro il link del file XML da caricare e incorpora al suo interno tutte le nuove funzionalità per il recupero e la visualizzazione dei dati.

Vantaggi: il principale vantaggio nell’utilizzo di questa tecnica è quello di creare un componente facilmente riutilizzabile che incapsulerà al suo interno tutte le nuove funzionalità, evitando la riscrittura dell’intera procedura ogni qualvolta si riproponga una esigenza analoga.
Il secondo vantaggio derivato da questo approccio è quello di mantenere il codice dell’applicazione pulito e ordinato. Il suo utilizzo all’interno di un progetto, infatti, richiederà pochissime righe di codice e risulterà davvero semplice da usare anche dagli sviluppatori meno esperti (pensiamo ad un progetto affrontato in team in cui i senior sviluppano i componenti e le parti complesse, mentre i junior li utilizzano semplicemente)

Di seguito l’output finale con i due combobox e le strutture XML da cui acquisiremo i dati:

001

Codice per l’utilizzo del nuovo componente:

002_flacode





Il FILE .FLA PRINCIPALE

Creiamo un nuovo file .fla, assegnando un nome a piacere, e trasciniamo sullo stage un componente Combobox (dal pannello Components -> User Interface) a cui assegneremo come nome istanza ‘countryCmb’.

Posizioniamo poi il seguente codice nel primo frame (o se preferite in una document class abbinata al .fla):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// ComboBox già presente sullo Stage
countryCmb.loadData = "xml/countries.xml";
countryCmb.addEventListener(Event.CHANGE, changeCmb);   
 
 
// Nuovo ComboBox istanziato dinamicamente
var namesCmb:ComboBoxXML = new ComboBoxXML();
namesCmb.loadData = "xml/names.xml";
namesCmb.addEventListener(Event.CHANGE, changeCmb);   
namesCmb.x = 200;
namesCmb.y = 50;
addChild(namesCmb)
 
// Output dell’elemento selezionato da entrambi i combobox
function changeCmb(e:Event):void {
	trace("Selected Item: ", e.currentTarget.selectedItem.label + "( " + e.currentTarget.selectedItem.data + " ) " );
}

Dal codice si evince che il nostro componente dovrà chiamarsi ComboBoxXML e che integrerà le seguenti funzionalità:

1) un metodo setter loadData() che accetterà come parametro il link del file xml da caricare
2) dispatch dell’evento CHANGE invocato alla selezione di un elemento del combobox

Mentre per il secondo punto non è necessaria alcuna operazione, dato che estendiamo la classe ComboBox ed ereditiamo quindi tale comportamento, per il primo punto sarà necessario creare tre classi:

a) ComboBoxXML.as che estende materialmente la classe ComboBox e integra il metodo pubblico loadData(xmlPath:String)
b) XmlLoader.as che gestisce il caricamento del file XML ed effettua i dispatch alla classe precedente degli eventi relativi al caricamento dati e ad eventuali errori
c) XmlEvent.as che estende la classe Event per la creazione di un custom event (evento personalizzato) per la gestione degli eventi relativi al caricamento dell’XML citati nel punto b)





ComboBoxXML.as: estendiamo la classe ComboBox

Creiamo un nuovo file chiamato ComboBoxXML.as che per semplicità posizioniamo nella stessa cartella del file .fla.

NOTA: per un ordinamento e gestione migliore dei files sarebbe più corretto posizionare le classi in diverse sotto-cartelle, creando a tutti gli effetti una suddivisione in package. Tuttavia, per rendere più semplice il tutorial posizioneremo tutte le classi nella root.

Innanzitutto importiamo due classi:

1
2
import fl.data.DataProvider;
import fl.controls.ComboBox;

La prima classe ci sarà utile per il popolamento del ComboBox al termine del caricamento dei dati, mentre la seconda è necessaria per estendere e utilizzare le funzionalità della classe ComboBox.

Utilizziamo quindi la keyword extends nella dichiarazione per fare in modo che la nostra classe erediti tutti i comportamenti della classe originale.

Creiamo poi il metodo setter loadData (utilizzando la parola chiave set), il cui unico parametro sarà rappresentato dal link al file XML da caricare.
All’interno di questo metodo istanziamo una nuova classe, che scriveremo nel paragrafo successivo, per la gestione e il caricamento dei dati e che effettuerà il dispatch di due eventi: COMPLETE e IO_ERROR, rispettivamente a caricamento dati avvenuto e in caso di link errato.

A caricamento dati avvenuto, verrà invocato il metodo onLoadXml() e popoleremo quindi il nostro combobox con i dati acquisiti dal file XML utilizzando la classe DataProvider.

ComboBoxXML.as:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
package 
{
 
	import fl.data.DataProvider;
	import fl.controls.ComboBox;
 
 
	public class ComboBoxXML extends ComboBox
	{
 
		private var xml:XML ;
 
 
		// Constructor
		public function ComboBoxXML()	{}
 
 
		/**
		* LOAD XML DATA
		*
		*/
    public function set loadData(xmlPath:String):void {
				var loadXml:XmlLoader = new XmlLoader(xmlPath)
				loadXml.addEventListener(XmlEvent.COMPLETE, onLoadXml)
				loadXml.addEventListener(XmlEvent.IO_ERROR, ioError)
		}
 
 
		/**
		* LOAD XML COMPLETED
		*
		*/
		private function onLoadXml(e:XmlEvent):void {
				xml = e.xmlData;
				this.dataProvider = new DataProvider(xml);
		}
 
 
 
		/**
		* LOAD XML FAILED: IO ERROR 
		*
		*/
		private function ioError(e:XmlEvent):void {
				trace("IOERror:: " + e)
		}
 
 
 
 
	}
}

Riapriamo il nostro file .fla, visualizziamo la libreria(F11), clicchiamo con il pulsante destro del mouse sul nostro componente Combobox e apriamo il menu LINKAGE.
Nel pannello Properties specificheremo la proprietà Class inserendo il nome della nostra nuova classe: ComboBoxXML.

003_linkage

NOTA: Se avessimo posizionato la classe in una sotto cartella avremmo dovuto inserire il percorso completo del package, ad esempio it.actionscript.esempio.ComboBoxXML

Così facendo, associamo la nostra nuova classe al ComboBox presente in libreria, in modo tale che il componente posizionato sullo stage non sia abbinato alla classe ComboBox standard di Flash ma faccia invece riferimento alla nuova classe.
Questo passaggio non sarebbe necessario se il componente fosse istanziato solo dinamicamente con il codice visto in precedenza:

1
var namesCmb:ComboBoxXML = new ComboBoxXML();




XmlLoader.as: caricamento dati da file XML

Questa semplice classe si occuperà di caricare i dati dal file xml e di restituirli alla nostra classe ComboBoxXML sfruttando la tecnica del dispatch.
La classe XmlLoader gestirà infatti i due eventi che abbiamo sopra menzionato (COMPLETE e IO_ERROR) e si occuperà proprio di avvertire (dispatch) la nostra classe principale ogni qualvolta si verificherà una delle due circostanze. Nel caso di caricamento avvenuto sarà inoltre necessario passare come parametro il contenuto XML, affinché la classe ComboBoxXML possa popolare il componente con i dati acquisiti.

Per effettuare questi dispatch purtroppo non potremo usare la classe Event di Flash, perché non gestisce il passaggio di parametri, e dovremo quindi necessariamente estenderla creando un evento personalizzato, XmlEvent, che a tutti gli effetti rappresenterà una nuova tipologia di evento.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
package 
{
 
	import flash.events.*
	import flash.net.*
	import flash.display.*
 
 
	public class XmlLoader extends Sprite
	{
 
		private var myXML:XML ;
		private var myXMLURL:URLRequest;
		private var myLoader:URLLoader;
 
 
		// Constructor
		public function XmlLoader(url:String) {
 
			myXML = new XML();
			myXMLURL = new URLRequest(url);
			myLoader = new URLLoader(myXMLURL);
			myLoader.addEventListener("complete", xmlLoaded);
			myLoader.addEventListener(IOErrorEvent.IO_ERROR, ioError);
		}
 
 
		// XML Load Completed
		private function xmlLoaded(event:Event):void{
 
			myXML = XML(myLoader.data);
			dispatchData(myXML);
 
		}
 
 
		// XML Load Failed (wrong url)
		private function ioError(event:IOErrorEvent):void {
 
			// Dispatch Custom XML Event 'ioError'
			var o:XmlEvent=new XmlEvent("ioError", myXML);
			dispatchEvent(o);
 
		}
 
 
		// Dispatch XML Data
		private function dispatchData(myXML:XML):void {
 
			// Dispatch Custom XML Event 'oncomplete'
			var o:XmlEvent=new XmlEvent("oncomplete", myXML);
			dispatchEvent(o);
 
		}
 
 
	}
 
}




XmlEvent.as: creazione di un Custom Event

Per creare quindi l’evento personalizzato sono necessari alcuni passaggi abbastanza standard nella creazione di un CustomEvent:

1) Creare una nuova classe che estende la classe Event
2) Definire le costanti dell’evento
3) Definire le proprietà da dispatchare
4) Modificare il costruttore affinché invochi la superclass e inizializzi le proprietà
5) Fare un override del metodo clone()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// Custom XML Event Class 
package
{
 
  import flash.events.Event;
 
  public class XmlEvent extends Event
  {
 
		public static const COMPLETE:String = "oncomplete";
		public static const IO_ERROR:String = "ioError";
 
		public var xmlData:XML;
 
		public function XmlEvent(type:String, data:XML) {
      super(type);
      this.xmlData = data;
    }
 
    override public function clone():Event  {
       return new XmlEvent(type, xmlData);
    }
 
 
  }
}

Download Flash CS3 Source Files

Leave your response!

Add your comment below, or trackback from your own site. You can also subscribe to these comments via RSS.

Be nice. Keep it clean. Stay on topic. No spam.

You can use these tags:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">

This is a Gravatar-enabled weblog. To get your own globally-recognized-avatar, please register at Gravatar.