No visualiza carga en Loader (AS3)
Buenas,
Estoy intentando cargar una serie de imagenes con AS3 pero al hacer addchild no me visualiza nada en la peli principal. El codigo es el siguiente:
package com.prosoft {
import flash.display.*;
import flash.events.*;
import flash.net.*;
public class XmlLoader extends Sprite {
private var xmlRuta:URLRequest;
private var imgRuta:URLRequest;
private var xmlLdr:URLLoader = new URLLoader();
private var imgLdr:Loader;
public function XmlLoader(_xml:String):void {
xmlRuta = new URLRequest(_xml);
xmlLdr.addEventListener(Event.COMPLETE, vuelcaXmlDatos);
xmlLdr.load(xmlRuta);
}
public function vuelcaXmlDatos(ev:Event):void {
var xmlLista:XMLList = new XMLList(ev.target.data);
for (var i:int=0 ; i < xmlLista..miniatura.length( ); i++){
cargaImagen(xmlLista..miniatura[i]);
}
}
public function cargaImagen(url:String):void {
imgLdr = new Loader();
imgLdr.load(new URLRequest(url)); imgLdr.contentLoaderInfo.addEventListener(Event.COMPLETE, pintaImagen);
}
public function pintaImagen(ev:Event):void {
addChild(imgLdr.content);
}
}
}
Las imagenes las carga bien, porque haciendo trace del content del Loader me dice que contiene un bitmap...
A ver si alguien sabe porque me pasa esto...
Un saludo
matmac Profesor Plus
Me parece que si quitas el ADDCHILD de la funcion que tiras ONCOMPLETE y lo pones fuera va a funcionar.
Puedes hacer un fade luego siempre que le des propiesdad alpha al incio.
ochionet
tiene pinta de ser un problema de seguridad en las cargas, el flash las carga las imagenes pero no las muestra, añade estas lineas
public function cargaImagen(url:String):void
{
var context:LoaderContext = new LoaderContext();
context.checkPolicyFile = true;
imgLdr = new Loader();
imgLdr.load(new URLRequest(url), context);
imgLdr.contentLoaderInfo.addEventListener(Event.COMPLETE, pintaImagen);
}
public function pintaImagen(ev:Event):void
{
addChild(ev.target.content);
}
kalesezeta
ya lo he solucionado, ahora la duda que me surge es si es posible añadir varias imagenes en un mismo loader para luego hacer una unica llamada y que se carguen todas a la vez. en ese caso, como se accedería a cada uno de los hijos del loader?
un saludo y gracias
ochionet
Depende de que quieres hacer con cada imagen, si tiene eventos, si sólo tiene efectos... lo de un loader con todas las imágenes a la vez entiendo que no se puede hacer, que yo sepa, por cada imagen tienes que hacer una carga, lo que si puedes hacer es controlar como quieres que se carguen, todas juntas a la vez o que comience la carga de la imagen una vez acabada la anterior.
Te recomiendo que trates a las imágenes como objetos diferentes, es decir, crea una clase que reciba la información por parámetro, y que sea esa clase la que se encargue de hacer la carga, de esta forma podrás atacar al objeto como a otro cualquiera. Cuanto más partas tu aplicación en trozos mas fácil te será trabajar y el código será más limpio.
También te recomiendo que mires como funciona el for each.
Saludos,
kalesezeta
Mas problemas... en un intento de separar bien las cosas me he dado cuenta que no puedo acceder a una xmllist declarada en una clase externa al ejecutar un trace en Main ( trace(cargador.xmlLista.length()); ) me da este error: 1178: Intento de acceso a una propiedad xmlLista no accesible mediante una referencia con tipo estático com.prosoft:XmlLoader.
tengo la clase Main así:
package {
import flash.display.*
import flash.events.*;
import flash.net.*;
import fl.motion.easing.*;
import com.gskinner.motion.*;
import com.prosoft.*;
public class Main extends MovieClip
{
private var cargador:XmlLoader;
public function Main():void {
cargador = new XmlLoader("datosXML.xml");
trace(cargador.xmlLista.length());
}
}
}
Y la otra clase:
package com.prosoft {
import flash.display.*;
import flash.events.*;
import flash.net.*;
public class XmlLoader extends Sprite {
var xmlRuta:URLRequest;
var xmlLdr:URLLoader;
var xmlLista:XMLList;
public function XmlLoader(_xml:String):void {
xmlRuta = new URLRequest(_xml);
xmlLdr = new URLLoader();
xmlLdr.addEventListener(Event.COMPLETE, vuelcaXmlDatos);
xmlLdr.load(xmlRuta);
}
public function vuelcaXmlDatos(ev:Event):void {
xmlLista = new XMLList(ev.target.data);
}
}
}
dourado
BuenAS,
Conoces el BULKLOADER?
Podrás hacer una "cola" de cargas y las podrás controlar individualmente se quieres.
Está bien documentado:
http://code.google.com/p/bulk-loader/downloads/list
Saludos.
ochionet
Veo que lo esta partiendo en trozos el código del Main.as, eso esta bien.
Ahora para acceder a la información del xml tendrías que hacer un getter, tendrías que crear métodos públicos para que sean accesibles desde el Main.
por ejemplo
public function get DevolverLongitud():Number
{
return longitud;
}
Desde el Main podrás ver el contenido llamando cargador.DevolverLongitud, al ser un getter no llevaría doble paréntesis como si estuvieras llamando a otra función.
Saludos
kalesezeta
Ya tengo toda la precarga hecha, lo unico que me queda es que me actualice el contenido del txt que tengo en principal.fla.
Mediante flash, me creo un nuevo TextField dinamico con nombre de instancia progrText_txt,
despues dentro de la clase ImgLoader.as (que esta dentro de la carpeta com.classes.etc...) al cargador de imagen le paso un evento progress que llama a una funcion, que entre otras cosas hace:
progrText_txt.text = "Progreso de carga: "+(pAcumImgs/pTot)*100+"%";
Pues bueno, al compilar me dice que nanai (1120: Acceso a una propiedad progrText_txt no definida.) dentro de la clase ImgLoader tengo bien importadas las clases Text, asi que imagino que sera error en la llamada a su propiedad text pero ahora mismo no caigo en cual es el error.
saludds
ochionet
No se si he terminado entender bien el problema, pero me da la impresión que intentas asignar el valor a progrText_txt desde una clase externa, cuando progrText_txt esta en el Main. Si es esto, puedes asignar el valor bien desde la clase externa utilizando parent hasta que llegues al Main o bien tendrás que poner un listener en la clase externa que vaya actualizando una variable conforme se va cargando y desde el Main con un Timer ir leyendo el valor de la variable publica que tienes dentro de la clase. Si lo haces con un Timer recuerda pararlo cuando la carga haya concluido.
Todo esto suponiendo que haya entendido el problema.
Saludos,
kalesezeta
Has entendido bien el problema, para darle solucion he utilizado el parent pero me sigue dando error:
1119: Acceso a una propiedad progrText_txt posiblemente no definida mediante una referencia con tipo estático flash.display:DisplayObjectContainer.
Para mas informacion, la clase desde donde quiero cambiar el texto del textfield esta en "com/prosoft/ImgLoader.as" y mi textfield esta creado en intro.fla, que envidentemente esta dos niveles por encima, junto con la clase Main.as...
Mi linea de codigo antes era esta:
progrText_txt.text = "Progreso de carga: "+(pAcumImgs/pTot)*100+"%";
Ahora es esta: (he probado con uno, con dos y hasta con tres parent por si acaso)
parent.parent.progrText_txt.text = "Progreso de carga: "+(pAcumImgs/pTot)*100+"%";
muchas gracias!
ochionet
aqui me pillas, yo siempre hago los TextField por código, y para este caso lo habría definido como public. Al estar en línea de tiempo no se si el objeto es público y por lo tanto puedas acceder a él. De todas formas, te hablo de memoria, me parece que te falta un parent más, pero no te lo puedo asegurar.
Otra forma es hacer un parent.parent.getChildByName(progText_txt).text = "Progreso de carga: "+(pAcumImgs/pTot)*100+"%";
Saludos,
kalesezeta
He probado de ambas formas y me sigue dando el mismo error. Desde Main.as si puedo acceder a el y cambiar el valor de text. pero desde la clase externa no y la verdad que me interesa mucho hacerlo de este modo. De todos modos pego el codigo de la clase ImgLoader por si alguien sabe como podria acceder y modificar a este u otros objetos de la peli principal:
ImgLoader
package com.prosoft {
import flash.display.*;
import flash.events.*;
import flash.net.*;
import flash.text.*;
public class ImgLoader extends Sprite {
private var xmlRuta:URLRequest;
private var xmlLdr:URLLoader;
private var xmlDatos:XML;
private var arrImgLoad:Array = new Array();
private var arrImagen:Array = new Array();
private var posX:int;
private var posY:int;
private var sumX:int;
var pTot:int=0;
var pAcumImgs:int=0;
var pAntImg:int=0;
public function ImgLoader():void {
posX=0;
posY=0;
sumX=0;
}
public function introXMLlista(_xml:String,_posX:int,_posY:int,_sumX:int):void{
xmlRuta = new URLRequest(_xml);
xmlLdr = new URLLoader();
if (_posX) posX = _posX;
if (_posY) posY = _posY;
if (_sumX) sumX = _sumX;
xmlLdr.addEventListener(Event.COMPLETE, vuelcaXmlDatos);
xmlLdr.load(xmlRuta);
}
private function vuelcaXmlDatos(ev:Event):void {
xmlDatos = new XML(xmlLdr.data);
var lista:XMLList = xmlDatos.opcion.miniatura;
for (var i:int=0; i <lista.length(); i++){
arrImgLoad[i] = new Loader();
arrImgLoad[i].contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, progrCargaImg);
arrImgLoad[i].contentLoaderInfo.addEventListener(Event.COMPLETE, pintaImagen);
arrImgLoad[i].load(new URLRequest(lista[i]));
}
xmlLdr.removeEventListener(Event.COMPLETE,vuelcaXmlDatos);
}
private function progrCargaImg(ev:Event):void{
if (!ev.target.bytesLoaded){
pTot+=ev.target.bytesTotal;
}
else if (ev.target.bytesLoaded){
pAcumImgs=(pAcumImgs+ev.target.bytesLoaded)-pAntImg;
pAntImg=ev.target.bytesLoaded;
if (ev.target.bytesLoaded==ev.target.bytesTotal){ //La imagen esta cargada, inicializamos "pAntImg".
pAntImg=0;
}
}
progText_txt.text = "Progreso de carga: "+(pAcumImgs/pTot)*100+"%";
}
private function pintaImagen(ev:Event):void {
var img:Bitmap = Bitmap(ev.target.content);
arrImagen.push(img);
if (arrImagen.length == arrImgLoad.length){
var pos:int=0;
for (var i:int=0; i<arrImagen.length;i++){
arrImagen[i].x=posX;
arrImagen[i].y=posY;
addChild(arrImagen[i]);
posX+=sumX;
}
}
}
}
}
kalesezeta
Alguien sabe explicarme o ponerme algun enlace sobre como acceder y modificar objetos que están en stage desde una clase externa?
Es que esto me urge un poco la verdad...
Mucha gracias
nueve
Hola kalesezeta, no me queda claro donde creas la instancia del ImgLoader. Si la creas en la clase Main, lo que puedes hacer es ponerle a escuchar eventos de ImgLoader. Para ello yo me crearía un evento personalizado y lo lanzaría en el progress de ImgLoader, enviando en el evento como propiedad (pAcumImgs/pTot)*100. Si el campo de texto lo tienes en Main también. En el manejador del evento en Main actualizaría el campo de texto con el valor de la propiedad del evento.
No se si me he explicao lo suficiente.
Me cuentas.
Un saludo
ochionet
Esta seguro que esto no funciona
parent.parent.getChildByName("progText_txt").text = "Progreso de carga: "+(pAcumImgs/pTot)*100+"%";
comprueba que la el textfield ademas tenga el mismo valor de instancia que el valor que estas asignando como variable dentro de las propiedades de la caja de texto, además verifica que la caja de texto es dinámica, el problema te viene por que no encuentra el objeto, por lo tanto tienes un problema para llegar a el. Si esta en el main la ruta es esa, pero el objeto tiene que estar bien instanciado para que lo encuentre.
Usuario desconocido
Prueba asignándolo así:
var clip:Object = parent.parent.getChildByName("progText_txt");
clip.text = "Progreso de carga: "+(pAcumImgs/pTot)*100+"%";
También puedes hacer el llamado al parent con: MovieClip(this.parent).getChildByName();