A classe Loader herda diretamente da classe DisplayObjectContainer, mas ela produz um erro ao tentar usar os métodos: addChild(), addChildAt(), removeChild(), removeChildAt() e setChildIndex(). Quando se usa um objeto Loader, o conteúdo carregado se torna o valor da propiedade content desse objeto, e é por isso que adicionando o objeto Loader na DisplayList é possível visualizar o conteúdo carregado. No entanto, ao adicionar o objeto Loader à DisplayList, o conteúdo carregado não tem acesso ao swf principal através dela.
Vamos fazer um exemplo para mostrar o que acontece quando o objeto Loader é adicionado à DisplayList. Crie um arquivo father1.fla e coloque a DocumentClass como Father1. Crie um arquivo de ActionScript com o nome Father1.as e coloque:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | package { import flash.display.MovieClip; import flash.display.Loader; import flash.events.Event; import flash.net.URLRequest; public class Father1 extends MovieClip { private var loader:Loader = new Loader(); public function Father1() { loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loaderComplete); loader.load(new URLRequest("son1.swf")); function loaderComplete(e:Event) { addChild(loader) } } } } |
Agora crie um arquivo son1.fla e coloque a DocumentClass como Son1. Selecione o primeiro frame da timeline, pressione F9 para acessar o painel de ações e coloque:
trace("Timeline > parent/parent.parent: "+parent,parent.parent)
Crie um arquivo de ActionScript com o nome Son1.as e coloque:
1 2 3 4 5 6 7 8 9 10 11 12 | package { import flash.display.Stage; import flash.display.MovieClip; public class Son1 extends MovieClip { public function Son1() { parent is Stage?trace("Constructor Method > parent/parent.parent: "+parent,parent.parent):trace("Constructor Method > parent: "+parent) } } } |
Feito isso, publique o son1.fla e verá o output:
Constructor Method > parent/parent.parent: [object Stage] null Timeline > parent/parent.parent: [object Stage] null
Ao criar o son1.swf, como ele é o arquivo principal, é nele que se encontra o Stage principal e pode ser acessado usando parent (tanto pela timeline, como pelo método construtor). E parent.parent retorna null porque o Stage principal é o primeiro objeto da DisplayList.
Agora publique o father1.fla e verá o output:
Constructor Method > parent: null Timeline > parent/parent.parent: [object Loader] null
Ao criar o father1.swf, ele carrega o son1.swf, que por sua vez é o conteúdo do objeto Loader. Ao adicionar o objeto Loader à DisplayList, ele executa o conteúdo do son1.swf (que gera o output). No output podemos ver que ao tentar acessar parent pelo método construtor de Son, o resultado vai ser null e parent.parent não é lido porque senão geraria um erro de compilação. Por outro lado, ao tentar acessar parent pela timeline, vai acessar o objeto Loader do father1.swf, porém parent.parent não acessa o contêiner do objeto Loader.
O exemplo acima mostra que adicionando o objeto Loader à DisplayList, não há forma do swf carregado se comunicar pela DisplayList com o swf principal.
No entanto, existe um modo de adicionar o conteúdo do swf carregado à DisplayList e permitir que ele se comunique com o swf principal. No lugar de adicionar o objeto Loader à DisplayList, se adiciona a propiedade content desse objeto (loader.content). Logo, você poderia acessar o swf carregado usando casting, MovieClip(loader.content), ou o swf principal também com casting, MovieClip(parent), além disso, ambas DocumentClasses deveriam ser dinâmicas. Mas para evitar tanta complicação, podemos simplificar o processo criando objetos MovieClip de referência.
Vamos fazer um exemplo de como um swf carregado pode se comunicar com o swf principal, e vice-versa, de forma simplificada. Crie um arquivo father2.fla e coloque a DocumentClass como Father2. Crie um arquivo de ActionScript com o nome Father2.as e coloque:
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 | package { import flash.display.MovieClip; import flash.display.Loader; import flash.events.Event; import flash.net.URLRequest; public class Father2 extends MovieClip { private var son:MovieClip; private var loader:Loader = new Loader(); public function Father2() { loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loaderComplete); loader.load(new URLRequest("son2.swf")); function loaderComplete(e:Event) { son = loader.content as MovieClip; addChild(son) son.init() } } public function traceMc() { trace("traceMc: "+son.mc) } } } |
Agora crie um arquivo son2.fla e crie um MovieClip no palco com nome de instância mc. Coloque a DocumentClass como Son2. Selecione o primeiro frame da timeline, pressione F9 para acessar o painel de ações e coloque:
1 | trace("Timeline > parent/parent.parent: "+parent,parent.parent) |
Crie um arquivo de ActionScript com o nome Son2.as e coloque:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | package { import flash.display.Stage; import flash.display.MovieClip; public class Son2 extends MovieClip { private var father:MovieClip; public function Son2() { parent is Stage?trace("Constructor Method > parent/parent.parent: "+parent,parent.parent):trace("Constructor Method > parent: "+parent) } public function init() { father = parent as MovieClip; trace("init parent/parent.parent: "+parent,parent.parent) father.traceMc(); } } } |
Feito isso, publique o son2.fla para criar o son2.swf. Não vou comentar sobre o output gerado nessa publicação porque o resultado é o mesmo do primeiro exemplo deste post. Agora publique o father2.fla e verá o output:
Constructor Method > parent: null Timeline > parent/parent.parent: [object Loader] null init parent/parent.parent: [object Father] [object Stage] traceMc: [object MovieClip]
Ao criar o father2.swf, o MovieClip son é usado como referência para o conteúdo do objeto Loader e se adiciona son à DisplayList. No output podemos ver que as duas primeiras linhas dão o mesmo resultado do primeiro exemplo deste post, ou seja, mesmo adicionando o conteúdo do objeto Loader à DisplayList, não há forma do swf carregado se comunicar através da timeline ou pelo método construtor. Porém, na terceira e quarta linha do output podemos ver que essa comunicação acontece quando se chama o método son.init(), que por sua vez acessa o parent e parent.parent do swf carregado e executa o método father.traceMc() do swf principal.
Conclusão: essa comunicação é possível a partir de qualquer escopo (com exceção da timeline e método construtor) e permite acessar instâncias e métodos (com exceção do construtor) declarados no escopo principal da DocumentClass, e também objetos adicionados ao palco em tempo de edição.

em 15 de novembro de 2009
preimeiro!
\o/
muito bom iguu!!
em 15 de novembro de 2009
OO
merd@! eu disse que não ia ler…
=/
em 16 de novembro de 2009
;D outra otima explicação do Igor
:)
em 16 de novembro de 2009
Ae Igor!!
Mais um hein, esse é super útil também, interagir swfs carregados e seus ‘pais’ é muito necessário, em quase tudo.
Excelente! Parabénzão!! =D
em 17 de novembro de 2009
valeuuuuuuuuuu, galera \o/
:D
em 17 de novembro de 2009
iguis é mára XD
mto bom mesmo!
em 18 de novembro de 2009
Opa!
Ótima publicação Iguis.
Eu particularmente acho esse um tópico super especial, e de grande valia!
em 15 de dezembro de 2009
Muito bom.. :P
Parabens
em 6 de janeiro de 2010
Parabéns brow, mto bom mesmo esta sua explicação.. me quebrou uma galháásso!
Só tenho uma dúvida, e se eu quiser acessar uma função e não um MovieClip? Tentei son.minhaFuncao(); e nao pega.
vlw
em 7 de janeiro de 2010
Olá Tiago,
você também pode acessar uma função, mas ela deve ser declarada no escopo da classe e que tenha um namespace que permita o acesso (por exemplo: ‘public’).
Dá uma olhada no segundo exemplo que mostra como fazer isso.
Obrigado! :D