leitura do artigo >

15
nov

Comunicação entre o swf carregado e o principal

Ao adicionar o objeto Loader à DisplayList, o conteúdo carregado por ele através do método load() não tem acesso ao swf principal através da DisplayList. Neste post explico um modo que permite essa comunicação entre o swf carregado e o principal.

Comentários (3) Comentários(10) Categorias Action Script3, Soluções

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.

Postado em 15-11-2009 por Igor Amendola
em Action Script3, Soluções

Share/Save/Bookmark

Comentários

  • Bruno Monteiro disse:
    em 15 de novembro de 2009

    preimeiro!
    \o/

    muito bom iguu!!

  • Bruno Monteiro disse:
    em 15 de novembro de 2009

    OO

    merd@! eu disse que não ia ler…

    =/

  • Rodrigo Lucas - Ne disse:
    em 16 de novembro de 2009

    ;D outra otima explicação do Igor
    :)

  • Eder Lima disse:
    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

  • Igor Amendola disse:
    em 17 de novembro de 2009

    valeuuuuuuuuuu, galera \o/
    :D

  • Álvaro Gomides disse:
    em 17 de novembro de 2009

    iguis é mára XD
    mto bom mesmo!

  • Pedro Lins disse:
    em 18 de novembro de 2009

    Opa!
    Ótima publicação Iguis.
    Eu particularmente acho esse um tópico super especial, e de grande valia!

  • Victor C Tavernari disse:
    em 15 de dezembro de 2009

    Muito bom.. :P

    Parabens

  • Tiago disse:
    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

  • Igor Amendola disse:
    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

 Escreva um Comentário

Seu nome

E-mail (não será publicado) (obrigatório)

Website

Comente

Security Code: