Tutorial Action Script 3 – 015

Tutorial Action Script 3 – 015

Em continuação a série de tutoriais sobre AS3…

Hoje vou falar pouco sobre novidades, mas vou apenas apresentar um exemplo pratico de como criar um painel personalizado usando apenas action script  3 e todos os conceitos que aprendemos até agora…

5.4. Classes, Exemplo Painel personalizado

Vamos a um exemplo prático, usando o flex o meu objectivo é fazer o seguinte:

Criar um painel personalizado que permita:

–    ser arrastado (drag & drop) na nossa aplicação
–    ter botões de maximizar, minimizar e restaurar
–    Adicionar efeitos de maximizar, minimizar e restaurar.

Vamos aplicar todos os conhecimentos adquiridos anteriormente bem como a utilização de algumas classes nativas de efeitos disponiveis no flex como efeitos que mais à frente falaremos. Este exemplo apenas funcionará no Flex, visto que o AS3 do flash ainda não suporta alguns pontos e classes de efeitos que foram adicionadas no Flex.

Vejam o seguinte código que foi devidamente comentado para perceberem facilmente toda a sua estrutura.
[coolcode lang=”actionscript”]

package com.msdevstudio
{
//imports necessários ao nosso painel / class
//Eventos

import flash.events.Event;
import flash.events.MouseEvent;

import mx.containers.Panel;
import mx.controls.Image;
import mx.core.Application;
import mx.effects.Move;
import mx.effects.Parallel;
import mx.effects.Resize;

//extendemos o nosso painel
public class customPanel extends Panel
{
//incluimos as nossas imagens de maximizar, minimizar e restaurar
//para a resposta do carregamento / troca das imagens seja imediata

[Embed(source=”maxBut.png”)] public var max:Class;

[Embed(source=”minBut.png”)] public var min:Class;

[Embed(source=”restBut.png”)] public var rest:Class;

//variaveis
//estados do painel

private var maximizado:Boolean = false;
private var minimizado:Boolean = false;

//imagens dos botões
private var minBut:Image;
private var maxBut:Image;

//usado para guardar os tamanhos e posições originais do nosso panel

private var originalSizeW:int;
private var originalSizeH:int;
private var originalPosX:int;
private var originalPosY:int;

//construtor da nossa class
public function customPanel()
{
//definimos alguns estilos do nosso panel para ficar mais agradável

this.setStyle(“headerHeight”,19);
this.setStyle(“borderThicknessBottom”, 0);
this.setStyle(“borderThicknessLeft”, 0);
this.setStyle(“borderThicknessTop”, 0);
this.setStyle(“borderThicknessRight”, 0);
this.title=”Painel 1″;
}

//re-escrevemos a função createChildren que o componente painel usa
//para definir o novo layout que ele terá, ou seja vamos adicionar
//os botões

override protected function createChildren():void {
super.createChildren();

//guardamos as posições e tamanhos originais
originalSizeW=this.unscaledHeight;
originalSizeH=this.unscaledHeight;
originalPosX=this.x;
originalPosY=this.y;

/**
Apenas vamos criar os botões se eles não existirem, temos
que fazer isto porque esta função é chamada sempre que é
adicionado um elemento novo ao painel, no caso de
adicionarem uma caixa de texto esta função é chamada de novo
e se não indicasse-mos o “if” ele iria criar novos botões
sempre que fosse chamada.
**/

//verificamos se o botão de minimizar existe
if(!minBut){
//criamos a nova imagem
minBut=new Image;

//atribuimos a class (imagem) min ao nosso botão e definimos
//alguns parametros
minBut.source=min;
minBut.visible=true;
minBut.toolTip=”Minimiza”;

/**
a imagem mostra o icon por defeito (seta), usamos os 3
metodos em baixo para que o botão se comporte como um icon e
apresente o cursor “hand” / mão.
**/
minBut.mouseChildren=false;
minBut.useHandCursor=true;
minBut.buttonMode=true;
//Evento para detectar quando foi clicada.
minBut.addEventListener(MouseEvent.CLICK, minOnClick, false, 0, true);

/**
adicionamos como filho. Aqui adicionamos no metodo rawChildrem que faz
um “overlay” à nossa imagem e vai apresenta-la em cima do painel, se
usarmos apenas this.addChild() o nosso botão iria aparecer dentro da
area util do painel e não no topo. Poderiamos usar também
this.titleBar.addChild() onde a titlebar é o topo do nosso painel.**/

this.rawChildren.addChild(minBut);
}

//o mesmo procedimento para a imagem de maximizar, notem que
//não defini posições, elas serão definidas mais abaixo.
if(!maxBut) {
maxBut=new Image;
maxBut.visible=true;
maxBut.source=max;
maxBut.toolTip=”Maximiza”;
maxBut.mouseChildren=false;
maxBut.useHandCursor=true;
maxBut.buttonMode=true;
maxBut.addEventListener(MouseEvent.CLICK, onClick, false, 0, true);
this.rawChildren.addChild(maxBut);
}

//adicionamos um listner para saber quando o titleBar foi
//clicado para iniciar o drag e drop

this .titleBar.addEventListener(MouseEvent.MOUSE_DOWN, beginDrag,false,0,true);
this .titleBar.addEventListener(MouseEvent.MOUSE_UP, endDrag,false,0,true);

// actualiza a displayList.
invalidateDisplayList();
}

/**
Aqui vamos subscrever o metdo chamado pelo invalidateDisplayList()
que vai ser chamado sempre que existam modificações a fazer no
nosso layout, em cima como lhe adcionei duas imagens forcei a
chamada da função em baixo para poder definir as posições dos meus
botões.**/

protected  override function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void{

super.updateDisplayList(unscaledWidth, unscaledHeight);
//definimos os tamanhos da nossa imagem
//ela por defeito está com 16px por 16px mas vamos nos certificar
//que elas ficam com esses tamanhos
minBut.setActualSize(16,16);
maxBut.setActualSize(16,16);

/**
Vamos definir a posição x e y dos nossos botões
o unscaledWidth indica-nos o tamanho “on-execution” do
nosso painel, ou seja o tamanho actual, poderiamos usar o
this.width, mas provocaria falhas no posicionamento visto
que se o painel for aumentado esta actualização do
this.height teria que aguardar pela actualização da
displayList, ou seja, o tamanho final depois de maximizado
apenas estaria disponivel no final da execução desta função.

Colocamos o botão de minimizar à direita do painel, mas
deixamos um espaço em px para o botão de maximizar
(-maxBut.width)**/

var xPos:Number = unscaledWidth – (minBut.width+maxBut.width);

// o botão ficará a 2px do topo
var yPos:Number = 2;

//posicionamos o botão na devida posição
minBut.move(xPos, yPos);

//usamos as mesmas variaveis em cima, mas agora para
//posicionar o botão de maximizar

// como vai ficar à direita subtraimos apenas o seu tamanho ao
//total do nosso painel
xPos=unscaledWidth – maxBut.width;
yPos=2;
//subtraimos 4px para que o botão fiquem mais perto do
//minimizar e mais afastado da lateral direita
maxBut.move(xPos-4,yPos);
}

// chamada para iniciar o drag do panel
private function beginDrag(evt:MouseEvent):void {
this.startDrag();
}

// chamada para parar o drag do panel
private function endDrag(evt:MouseEvent):void {
this.stopDrag();

/**
Ao parar temos que guardar a posição em que o painel foi
largado para que ao restaurar o painel ir para a ultima
posição onde foi deixado.
**/
originalPosX=this.x;
originalPosY=this.y;
}

//chamada quando o botão de minimizar é clicado.
private function minOnClick(evt:MouseEvent):void {

/**
Vamos inicializar alguns efeitos para executar na transição do
nosso painel para o estado minimizado
paralel, usado para exectuatr mais que um efeito ao mesmo tempo
os efeitos executados por este paralel serão so seus child’s
(efeitos)**/

var ambos:Parallel = new Parallel;

//efeito de mover
var moveP:Move = new Move;

//efeito de dimensionar
var dim:Resize = new Resize;

//definimos o target, a instancia, que será alvo do nossos efeitos
//dentro do paralel
ambos.target=this;

//movemos o painel para o x=0;
moveP.xTo=0;
// a nivel de y, movemos para o fundo da aplicação deixando apenas
//19px de altura
// que serão os mesmos 19px com que icará o painel de altura depois
//de o efeito resize
moveP.yTo=Application.application.height-19;

//efeito para dimensionar, alture=19, comprimento=150
dim.heightTo=19;
dim.widthTo=150;

//adiciona-mos o efeito de mover e dimensionar ao nosso paralel
ambos.addChild(moveP);
ambos.addChild(dim);
//duração do efeito
ambos.duration=250;
//iniciamos o efeito
ambos.play();

//usamos a variavel para indicar que o estado de minimizado está
//activo
minimizado=true;
// como está minimizado o botão de maximizar para a ser substituido
//pela imagem de restaurar
maxBut.source=rest;
//toolTip informativa
maxBut.toolTip=”Restaura”;

}
//Funcção chamado quando o botão de maximizar é clicado.
private function onClick(evt:MouseEvent):void {
//usamos as mesmas instancia de efeitos que no minimiza
var ambos:Parallel = new Parallel;
var dim:Resize = new Resize;
var moveP:Move = new Move;

ambos.target=this;

/**
O painel vai-se comportar da mesma maneira caso esteja
minimizado ou maximizado
já que a animação vai ser sempre a mesma = restaurar
**/
if(maximizado==true || minimizado==true ) {
/**
Definimos a altura e posição originais do nosso painel
estas posições podem ser afectadas pelo drop, por isso sao
automaticamente actualizadas.
**/
dim.heightTo=originalSizeH;
dim.widthTo=originalSizeW;
moveP.xTo=originalPosX;
moveP.yTo=originalPosY;

//passa a estar no estado original
maximizado=false;
minimizado=false;
//mudamos a imagem para maximizar
maxBut.source=max;
maxBut.toolTip=”Maximiza”;
//duração do efeito
ambos.duration=100;
//adicionamos como filhos do nosso paralel
ambos.addChild(dim);
ambos.addChild(moveP);
//iniciamos o efeito
ambos.play();
}
else {
/**usado para maximizar o painel caso o nosso painel esteja na
posição original:
altura em que o maximizado=false; e minimizado=false;
definimos como tamanho a totalidade da area da nossa
aplicação**/
dim.heightTo=Application.application.height;
dim.widthTo=Application.application.width;
//movemos para a posição x=y=0
moveP.xTo=0;
moveP.yTo=0;
//o seu estado passa a ser maximizado
maximizado=true;
maxBut.toolTip=”Restaura”;
//mudamos para a imagem maximizada
maxBut.source=rest;
//duração do efeito
ambos.duration=100;
//childs
ambos.addChild(dim);
ambos.addChild(moveP);
//play
ambos.play();
}
}
}
}
[/coolcode]

Como podem ver, o processo é muito lógico e bem simples de executar, neste momento ao adicionares o vosso customPanel a uma aplicação, ele ficará exactamente igual a um painel normal do flex, mas a magia vem na hora da execução da vossa aplicação…querem ver? cliquem aqui para ver o resultado final.

Para que este código funcione correctamente, necessitam de ter as 3 imagens correspondentes ao botão de maximizar, minimizar e restaurar, mas isso fica à vossa escolha, segue a dica do iconfinder para um esquema de icons. Gravem com os nomes: restBut.png, maxBut.png,  minBut.png ou alterem o código para os vossos icons. Estes icons devem ser colocados na mesma pasta (com/msdevstudio) que o nosso customPanel.as (ficheiro em cima).

E pronto, têm um painel pronto a ser usado nas vossas aplicações que suporta Drag & Drop, Maximizar, Minimizar e Restaurar… muito simples, pratico e eficiente.

Se conseguiram entender o processo posso afirmar que estão prontos para se aventurar de armas e bagagens pelo mundo do action script e suas classes.

No Próximo tutorial iremos falar de filtros e efeitos….

Duvidas? use o forum.

Abraço.

p.s. O código não fica tabulado devido a uma falha da plugin, alguém conhece uma plugin alternativa para apresentar código as3?? No entanto segue a class customPanel para download.

package com.msdevstudio

{

//imports necessários ao nosso painel / class

//Eventos

import flash.events.Event;

import flash.events.MouseEvent;

import mx.containers.Panel;

import mx.controls.Image;

import mx.core.Application;

import mx.effects.Move;

import mx.effects.Parallel;

import mx.effects.Resize;

//extndemos o nosso painel

public class customPanel extends Panel

{

//incluimos as nossas imagens de maximizar, minimizar e resturar

//para a resposta do carregamento / troca das imagens seja imediata

[Embed(source=“maxBut.png”)]

public var max:Class;

[Embed(source=“minBut.png”)]

public var min:Class;

[Embed(source=“restBut.png”)]

public var rest:Class;

//variaveis

//estados do painel

private var maximizado:Boolean = false;

private var minimizado:Boolean = false;

//imagens dos botões

private var minBut:Image;

private var maxBut:Image;

//usado para guardar os tamanhos e posições originais do nosso panel

private var originalSizeW:int;

private var originalSizeH:int;

private var originalPosX:int;

private var originalPosY:int;

//construtor da nossa class

public function customPanel()

{

//definimos alguns estilos do nosso panel para ficar mais agradável

this.setStyle(“headerHeight”,19);

this.setStyle(“borderThicknessBottom”, 0);

this.setStyle(“borderThicknessLeft”, 0);

this.setStyle(“borderThicknessTop”, 0);

this.setStyle(“borderThicknessRight”, 0);

this.title=“Painel 1″;

}

//re-escrevemos a função createChildren que o componente painel usa //para definir o novo layout que ele terá, ou seja vamos adicionar //os botões

override protected function createChildren():void {

super.createChildren();

//guardamos as posições e tamanhos originais

originalSizeW=this.unscaledHeight;

originalSizeH=this.unscaledHeight;

originalPosX=this.x;

originalPosY=this.y;

//apenas vamos criar os botões se eles não existirem, temos //que fazer isto porque esta função é chamada sempre que é //adicionado um elemento novo ao painel, no caso de //adicionarem uma caixa de texto esta função é chamada de novo //e se não indicasse-mos o “if” ele iria criar novos botões //sempre que fosse chamada

//verificamos se o botão de minimizar existe

if(!minBut){

//criamos a nova imagem

minBut=new Image;

//atribuimos a class (imagem) min ao nosso botão e definimos //alguns parametros

minBut.source=min;

minBut.visible=true;

minBut.toolTip=“Minimiza”;

//a imagem mostra o icon por defeito (seta), usamos os 3 //metodos em baixo para que o botão se comporte como um icon e //apresente o cursor “hand” / mão.

minBut.mouseChildren=false;

minBut.useHandCursor=true;

minBut.buttonMode=true;

//Evento para detectar quando foi clicada.

minBut.addEventListener(MouseEvent.CLICK, minOnClick, false, 0, true);

//adicionamos como filho. Aqui adicionamos no metodo rawChildrem que faz //um “overlay” à nossa imagem e vai apresenta-la em cima do painel, se //usarmos apenas this.addChild() o nosso botão iria aparecer dentro da //area util do painel e não no topo. Poderiamos usar também //this.titleBar.addChild() onde a titlebar é o topo do nosso painel

this.rawChildren.addChild(minBut);

}

//o mesmo procedimento para a imagem de maximizar, notem que //não defini posições, elas serão definidas mais abaixo.

if(!maxBut) {

maxBut=new Image;

maxBut.visible=true;

maxBut.source=max;

maxBut.toolTip=“Maximiza”;

maxBut.mouseChildren=false;

maxBut.useHandCursor=true;

maxBut.buttonMode=true;

maxBut.addEventListener(MouseEvent.CLICK, onClick, false, 0, true);

this.rawChildren.addChild(maxBut);

}

//adicionamos um listner para saber quando o titleBar foi //clicado para iniciar o drag e drop

this.titleBar.addEventListener(MouseEvent.MOUSE_DOWN, beginDrag,false,0,true);

this.titleBar.addEventListener(MouseEvent.MOUSE_UP, endDrag,false,0,true);

// actualiza a displayList.

invalidateDisplayList();

}

//aqui vamos subscrever o metdo chamado pelo invalidateDisplayList() //que vai ser chamado sempre que existam modificações a fazer no // nosso layout, em cima como lhe adcionei duas imagens forcei a

//chamada da função em baixo para poder definir as posições dos meus //botões.

protected override function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void{

super.updateDisplayList(unscaledWidth, unscaledHeight);

//definimos os tamanhos da nossa imagem

//ela por defeito está com 16px por 16px mas vamos certificar- //nos que elas ficam com esses tamanhos

minBut.setActualSize(16,16);

maxBut.setActualSize(16,16);

//vamos definir a posição x e y dos nossos botões

// o unscaledWidth indica-nos o tamanho “on-execution” do //nosso painel, ou seja o tamanho actual, poderiamos usar o // this.width, mas provocaria falhas no posicionamento visto //que se o painel for aumentado esta actualização do //this.height teria que aguardar pela actualização da //displayList, ou seja, o tamanho final depois de maximizado //apenas estaria disponivel no final da execução desta função.

// colocamos o botão de minimizar à direita do painel, mas //deixamos um espaço em px para o botão de maximizar

// (-maxBut.width)

var xPos:Number = unscaledWidth – (minBut.width+maxBut.width);

// o botão ficará a 2px do topo

var yPos:Number = 2;

//posicionamos o botão na devida posição

minBut.move(xPos, yPos);

//usamos as mesmas variaveis em cima, mas agora para //posicionar o botão de maximizar

// como vai ficar à direita subtraimos apenas o seu tamanho ao //total do nosso painel

xPos=unscaledWidth – maxBut.width;

yPos=2;

//subtraimos 4px para que o botão fiquem mais perto do //minimizar e mais afastado da lateral direita

maxBut.move(xPos-4,yPos);

}

// chamada para iniciar o drag do panel

private function beginDrag(evt:MouseEvent):void {

this.startDrag();

}

// chamada para parar o drag do panel

private function endDrag(evt:MouseEvent):void {

this.stopDrag();

//ao parar temos que guardar a posição em que o painel foi //largado para que ao restaurar o painel ir para a ultima //posição onde foi deixado.

originalPosX=this.x;

originalPosY=this.y;

}

//chamada quando o botão de minimizar é clicado.

private function minOnClick(evt:MouseEvent):void {

//vamos inicializar alguns efeitos para executar na transição do //nosso painel para o estado minimizado

//paralel, usado para exectuatr mais que um efeito ao mesmo tempo

//os efeitos executados por este paralel serão so seus child’s //(efeitos)

var ambos:Parallel = new Parallel;

//efeito de mover

var moveP:Move = new Move;

//efeito de dimensionar

var dim:Resize = new Resize;

//definimos o target, a instancia, que será alvo do nossos efeitos //dentro do paralel

ambos.target=this;

//movemos o painel para o x=0;

moveP.xTo=0;

// a nivel de y, movemos para o fundo da aplicação deixando apenas //19px de altura

// que serão os mesmos 19px com que icará o painel de altura depois //de o efeito resize

moveP.yTo=Application.application.height-19;

//efeito para dimensionar, alture=19, comprimento=150

dim.heightTo=19;

dim.widthTo=150;

//adiciona-mos o efeito de mover e dimensionar ao nosso paralel

ambos.addChild(moveP);

ambos.addChild(dim);

//duração do efeito

ambos.duration=250;

//iniciamos o efeito

ambos.play();

//usamos a variavel para indicar que o estado de minimizado está //activo

minimizado=true;

// como está minimizado o botão de maximizar para a ser substituido //pela imagem de restaurar

maxBut.source=rest;

//toolTip informativa

maxBut.toolTip=“Restaura”;

}

//Funcção chamado quando o botão de maximizar é clicado.

private function onClick(evt:MouseEvent):void {

//usamos as mesmas instancia de efeitos que no minimiza

var ambos:Parallel = new Parallel;

var dim:Resize = new Resize;

var moveP:Move = new Move;

ambos.target=this;

//O painel vai-se comportar da mesma maneira caso esteja //minimizado ou maximizado

//já que a animação vai ser sempre a mesma = restaurar

if(maximizado==true || minimizado==true ) {

//definimos a altura e posição originais do nosso painel

//estas posições podem ser afectadas pelo drop, por isso sao //automaticamente actualizadas

dim.heightTo=originalSizeH;

dim.widthTo=originalSizeW;

moveP.xTo=originalPosX;

moveP.yTo=originalPosY;

//passa a estar no estado original

maximizado=false;

minimizado=false;

//mudamos a imagem para maximizar

maxBut.source=max;

maxBut.toolTip=“Maximiza”;

//duração do efeito

ambos.duration=100;

//adicionamos como filhos do nosso paralel

ambos.addChild(dim);

ambos.addChild(moveP);

//iniciamos o efeito

ambos.play();

}

else {

//usado para maximizar o painel caso o nosso painel esteja na //posição original:

//altura em que o maximizado=false; e minimizado=false;

//definimos como tamanho a totalidade da area da nossa //aplicação

dim.heightTo=Application.application.height;

dim.widthTo=Application.application.width;

//movemos para a posição x=y=0

moveP.xTo=0;

moveP.yTo=0;

//o seu estado passa a ser maximizado

maximizado=true;

maxBut.toolTip=“Restaura”;

//mudamos para a imagem maximizada

maxBut.source=rest;

//duração do efeito

ambos.duration=100;

//childs

ambos.addChild(dim);

ambos.addChild(moveP);

//play

ambos.play();

}

}

}

}


7 comments

add yours
  • Marcelo Sato January 5, 2010

    Muito interessante seu exemplo, para ficar melhor só faltou o código estar com identação …
    Abraço!

  • Mário Santos January 5, 2010

    Oi Marcelo, pois é… mas esse é um problema da plugin… no entanto coloquei a class para download no final :)

    Abraço!

  • Pierre January 15, 2010

    Mario,

    Não se se vou falar besteira, mas no meu blog, eu estava escrevendo uma série de tutoriais sobre objective-c e tinha vários problemas em relação aos códigos digitados. Ele fica hospedado no blogger, o que resolveu foi colocar o código entre as tags só desta forma eu resolvi.

    Abraços.

    Pierre

  • Ricardo January 28, 2010

    Muito bom…

    parabéns pelo tutorial. É muito explicito e útil …

  • Helena September 6, 2010

    Muito bom o seu tutorial!! Bacana mesmo. Dificil de achar. Mas, é muito difícil colocar delimitação na janela? Tipo iGoogle, que a janela tem um lugar fixo para ela ficar?

  • Mário Santos September 6, 2010

    Oi Helena, Obrigado.

    Quanto ao ser fixo, basta eliminar a função drag/drop e definir inicialmente a posição da janela, desta forma ela nunca saira do lugar… ;)

    Cumps.

  • Mauro Alberto December 7, 2010

Leave a Comment

Post