Ouvintes de evento

Flash Player 9 e posterior, Adobe AIR 1.0 e posterior

Os ouvintes de evento, também chamados de manipuladores de evento, são funções executadas pelo Flash Player e pelo AIR em resposta a eventos específicos. A adição de um ouvinte de evento é um processo de duas etapas. Primeiro, crie um método de função ou classe a ser executado pelo Flash Player ou AIR em resposta ao evento. Às vezes, isso é chamado de função de ouvinte ou de manipulador de evento. Segundo, use o método addEventListener() para registrar a função de ouvinte no destino do evento ou em qualquer objeto da lista de exibição ao longo do fluxo de evento adequado.

Criação de uma função de ouvinte

A criação de funções de ouvinte é uma das diferenças entre o modelo de evento do ActionScript 3.0 e o modelo de evento DOM. No modelo de evento DOM, existe uma distinção clara entre um ouvinte de evento e uma função de ouvinte: um ouvinte de evento é uma ocorrência de uma classe que implementa a interface EventListener, enquanto a função de ouvinte é um método dessa classe chamado handleEvent() . No modelo de evento DOM, a ocorrência da classe que contém a função de ouvinte é registrada, não a função de ouvinte propriamente dita.

No modelo de evento do ActionScript 3.0, não existe diferença entre um ouvinte de evento e uma função de ouvinte. O ActionScript 3.0 não tem uma interface EventListener e as funções de ouvinte podem ser definidas fora de uma classe ou como parte dela. Além disso, as funções de ouvinte não precisam ser chamadas de handleEvent() - elas podem ser chamadas com qualquer identificador válido. No ActionScript 3.0, o nome da função de ouvinte real é registrado.

Função de ouvinte definida fora de uma classe

O código a seguir cria um arquivo SWF simples que exibe um quadrado vermelho. Uma função de ouvinte chamada clickHandler() , que não faz parte de uma classe, ouve os eventos de clique de mouse no quadrado vermelho.

package 
{ 
    import flash.display.Sprite; 
 
    public class ClickExample extends Sprite 
    { 
        public function ClickExample() 
        { 
            var child:ChildSprite = new ChildSprite(); 
            addChild(child); 
        } 
    } 
} 
 
import flash.display.Sprite; 
import flash.events.MouseEvent; 
 
class ChildSprite extends Sprite 
{ 
    public function ChildSprite() 
    { 
        graphics.beginFill(0xFF0000); 
        graphics.drawRect(0,0,100,100); 
        graphics.endFill(); 
        addEventListener(MouseEvent.CLICK, clickHandler); 
    } 
} 
 
function clickHandler(event:MouseEvent):void 
{ 
    trace("clickHandler detected an event of type: " + event.type); 
    trace("the this keyword refers to: " + this); 
}

Quando um usuário interage com o arquivo SWF resultante clicando no quadrado, o Flash Player ou AIR gera a seguinte saída de traço:

clickHandler detected an event of type: click 
the this keyword refers to: [object global]

Observe que o objeto de evento é transmitido como um argumento para clickHandler() . Isso permite que a função de ouvinte examine o objeto de evento. Neste exemplo, use a propriedade type do objeto de evento para certificar-se de que o evento é um evento de clique.

O exemplo também verifica o valor da palavra-chave this . Nesse caso, this representa o objeto global, o que faz sentido porque a função é definida fora de um objeto ou classe personalizado.

Função de ouvinte definida como um método de classe

O exemplo a seguir é idêntico ao anterior que define a classe ClickExample, mas a função clickHandler() é definida como um método da classe ChildSprite:

package 
{ 
    import flash.display.Sprite; 
 
    public class ClickExample extends Sprite 
    { 
        public function ClickExample() 
        { 
            var child:ChildSprite = new ChildSprite(); 
            addChild(child); 
        } 
    } 
} 
 
import flash.display.Sprite; 
import flash.events.MouseEvent; 
 
class ChildSprite extends Sprite 
{ 
    public function ChildSprite() 
    { 
        graphics.beginFill(0xFF0000); 
        graphics.drawRect(0,0,100,100); 
        graphics.endFill(); 
        addEventListener(MouseEvent.CLICK, clickHandler); 
    } 
    private function clickHandler(event:MouseEvent):void 
    { 
        trace("clickHandler detected an event of type: " + event.type); 
        trace("the this keyword refers to: " + this); 
    } 
}

Quando um usuário interage com o arquivo SWF resultante clicando no quadrado vermelho, o Flash Player ou AIR gera a seguinte saída de traço:

clickHandler detected an event of type: click 
the this keyword refers to: [object ChildSprite]

Observe que a palavra-chave this faz referência à ocorrência de ChildSprite chamada child . Este comportamento é diferente do ActionScript 2.0. Caso já tenha usado componentes no ActionScript 2.0, talvez se lembre que, quando um método de classe era transmitido para UIEventDispatcher.addEventListener() , o escopo do método ia até o componente que transmite o evento em vez da classe na qual o método de ouvinte era definido. Em outras palavras, se você utilizou essa técnica no ActionScript 2.0, a palavra-chave this fazia referência ao componente que transmite o evento, não à ocorrência de ChildSprite.

Isso foi um problema significativo para alguns programadores, pois não permitia o acesso a outros métodos e propriedades da classe que contém o método de ouvinte. Como solução temporária, os programadores do ActionScript 2.0 podiam usar a classe mx.util.Delegate para alterar o escopo do método de ouvinte. No entanto, isso não é mais necessário porque o ActionScript 3.0 cria um método vinculado quando addEventListener() é chamado. Em resultado disso, a palavra-chave this faz referência à ocorrência de ChildSprite chamada child , e o programador tem acesso a outros métodos e propriedades da classe ChildSprite.

Ouvinte de evento que não deve ser usado

Existe uma terceira técnica que permite criar um objeto genérico com uma propriedade que aponta para uma função de ouvinte atribuída dinamicamente, mas essa técnica não é recomendada. Ela será discutida aqui porque foi muito usada no ActionScript 2.0, mas não deve ser usada no ActionScript 3.0. Essa técnica não é recomendada porque a palavra-chave this fará referência ao objeto global em vez do objeto de ouvinte.

O exemplo a seguir é idêntico ao exemplo anterior da classe ClickExample, mas a função de ouvinte é definida como parte de um objeto genérico chamado myListenerObj :

package 
{ 
    import flash.display.Sprite; 
 
    public class ClickExample extends Sprite 
    { 
        public function ClickExample() 
        { 
            var child:ChildSprite = new ChildSprite(); 
            addChild(child); 
        } 
    } 
} 
 
import flash.display.Sprite; 
import flash.events.MouseEvent; 
 
class ChildSprite extends Sprite 
{ 
    public function ChildSprite() 
    { 
        graphics.beginFill(0xFF0000); 
        graphics.drawRect(0,0,100,100); 
        graphics.endFill(); 
        addEventListener(MouseEvent.CLICK, myListenerObj.clickHandler); 
    } 
} 
 
var myListenerObj:Object = new Object(); 
myListenerObj.clickHandler = function (event:MouseEvent):void 
{ 
        trace("clickHandler detected an event of type: " + event.type); 
        trace("the this keyword refers to: " + this); 
}

Os resultados do traço serão similares a:

clickHandler detected an event of type: click 
the this keyword refers to: [object global]

Você talvez pensasse que this faria referência a myListenerObj e que a saída de traço seria [object Object] , mas a referência foi feita ao objeto global. Ao transmitir o nome de uma propriedade dinâmica como um argumento para addEventListener() , o Flash Player ou AIR não consegue criar um método vinculado. Isso ocorre porque, quando está transmitindo o parâmetro listener , você não está transmitindo nada mais do que o endereço de memória da função de ouvinte, e o Flash Player e AIR não conseguem vincular esse endereço de memória com a ocorrência de myListenerObj .

Gerenciamento de ouvintes de evento

Você pode gerenciar suas funções de ouvinte usando os métodos da interface IEventDispatcher. A interface IEventDispatcher é a versão ActionScript 3.0 da interface EventTarget do modelo de evento DOM. Embora o nome IEventDispatcher possa transmitir a ideia de que o objetivo principal é enviar (ou despachar) objetos de evento, os métodos dessa classe são usados com mais frequência para registrar, verificar e remover ouvintes de evento. A interface IEventDispatcher define cinco métodos, como mostra o código a seguir:

package flash.events 
{ 
    public interface IEventDispatcher 
    { 
        function addEventListener(eventName:String,  
                        listener:Object, 
                        useCapture:Boolean=false, 
                        priority:Integer=0, 
                        useWeakReference:Boolean=false):Boolean; 
 
        function removeEventListener(eventName:String,  
                    listener:Object, 
                    useCapture:Boolean=false):Boolean; 
 
        function dispatchEvent(eventObject:Event):Boolean; 
 
        function hasEventListener(eventName:String):Boolean; 
        function willTrigger(eventName:String):Boolean; 
    } 
}

A API do Flash Player implementa a interface IEventDispatcher com a classe EventDispatcher, que serve como base para todas as classes que podem ser destinos de evento ou fazer parte de um fluxo de evento. Por exemplo, a classe DisplayObject é herdada da classe EventDispatcher. Isso significa que todos os objetos da lista de exibição têm acesso aos métodos da interface IEventDispatcher.

Adição de ouvintes de evento

O método addEventListener() é a força motriz da interface IEventDispatcher. Você pode usá-lo para registrar suas funções de ouvinte. Os dois parâmetros necessários são type e listener . Use o parâmetro type para especificar o tipo de evento. Use o parâmetro listener para especificar a função de ouvinte que será executada quando o evento ocorrer. O parâmetro listener pode ser uma referência a um método de classe ou função.

Não use parênteses quando especificar o parâmetro listener . Por exemplo, a função clickHandler() é especificada sem parênteses na seguinte chamada do método addEventListener() :
addEventListener(MouseEvent.CLICK, clickHandler)

O parâmetro useCapture do método addEventListener() permite controlar a fase do fluxo de evento na qual o ouvinte estará ativo. Se useCapture for definido como true , o ouvinte estará ativo durante a fase de captura do fluxo de evento. Se useCapture for definido como false , o ouvinte estará ativo durante as fases de destinos e de bolhas do fluxo de evento. Para ouvir um evento durante todas as fases do fluxo de evento, chame addEventListener() duas vezes, uma com useCapture definido como true e outra com useCapture definido como false .

O parâmetro priority do método addEventListener() não é uma parte oficial do modelo de evento DOM nível 3. Ele está incluído no ActionScript 3.0 para fornecer mais flexibilidade para organizar os ouvintes de evento. Ao chamar addEventListener() , você pode definir a prioridade desse ouvinte de evento transmitindo um valor inteiro como o parâmetro priority . O valor padrão é 0, mas é possível definir valores inteiros negativos ou positivos. Quanto maior o número, mais rapidamente o ouvinte de evento será executado. Os ouvintes de evento com a mesma prioridade são executados na ordem em que foram adicionados, de modo que o ouvinte adicionado primeiro será executado antes.

O parâmetro useWeakReference permite especificar se a referência à função de ouvinte será fraca ou normal. Se esse parâmetro for definido como true , você poderá evitar situações nas quais as funções de ouvinte persistem na memória mesmo quando não são mais necessárias. O Flash Player e o AIR usam uma técnica chamada coleta de lixo para apagar da memória os objetos que não são mais usados. Um objeto não é mais necessário quando não existe nenhuma referência a ele. O coletor de lixo ignora as referências fracas e, desse modo, uma função de ouvinte que tem apenas uma referência fraca se qualifica para a coleta de lixo.

Remoção de ouvintes de eventos

Você pode usar o método removeEventListener() para remover um ouvinte de evento que não seja mais necessário. É uma boa ideia remover o ouvinte que não será mais usado. Entre os parâmetros obrigatórios estão eventName e listener , que são os mesmos parâmetros obrigatórios no método addEventListener() . Não se esqueça que é possível ouvir eventos durante todas as fases chamando addEventListener() duas vezes, uma com useCapture definido como true e outra definido como false . Para remover os dois ouvintes de evento, seria necessário chamar removeEventListener() duas vezes, uma com useCapture definido como true e outra definido como false .

Envio de eventos

O método dispatchEvent() pode ser usado por programadores avançados para enviar um objeto de evento personalizado para o fluxo de evento. O único parâmetro aceito por esse método é uma referência a um objeto de evento, que deve ser uma ocorrência da classe Event ou uma subclasse de Event. Assim que é enviada, a propriedade target do objeto de evento é definida como o objeto no qual dispatchEvent() foi chamado.

Verificação da existência de ouvintes de eventos

Os dois métodos finais da interface IEventDispatcher fornecem informações úteis sobre a existência de ouvintes de evento. O método hasEventListener() retornará true se um ouvinte de evento for encontrado para um tipo de evento específico em um determinado objeto da lista de exibição. O método willTrigger() também retornará true se um ouvinte for encontrado para um objeto específico da lista de exibição, mas willTrigger() procurará ouvintes nesse objeto de exibição e em todos os ancestrais desse objeto em todas as fases do fluxo de evento.

Eventos de erro sem ouvintes

As exceções, em vez dos eventos, são o principal mecanismo de manipulação de erros no ActionScript 3.0, mas a manipulação de exceções não funciona para operações assíncronas, como o carregamento de arquivos. Se ocorrer um erro durante uma operação assíncrona, o Flash Player e o AIR enviarão um objeto de evento de erro. Se nenhum ouvinte for criado para o evento de erro, as versões do depurador do Flash Player e do AIR exibirão uma caixa de diálogo com informações sobre o erro. Por exemplo, a versão do depurador do Flash Player exibe a caixa de diálogo a seguir, que descreve o erro quando o aplicativo tentar carregar um arquivo a partir de URLs inválidas:

A maioria dos eventos de erro baseia-se na classe ErrorEvent e, desse modo, tem uma propriedade chamada text que é usada para armazenar a mensagem de erro exibida pelo Flash Player ou AIR. As duas exceções são as classes StatusEvent e NetStatusEvent. Essas duas classes têm uma propriedade level ( StatusEvent.level e NetStatusEvent.info.level ). Quando o valor da propriedade level é " error ", esses tipos de evento são considerados eventos de erro.

Um evento de erro não interrompe a execução do arquivo SWF. Ele será manifestado somente como uma caixa de diálogo nas versões do depurador dos plug-ins do navegador e de players dedicados, como uma mensagem no painel de saída do player de criação e como uma entrada no arquivo de log do Adobe Flash Builder. Ele não se manifestará de modo algum nas versões do Flash Player ou do AIR.