22 мая 2011 г.

Пишем простой таймер

В этом практическом уроке мы рассмотрим создание и использование дополнительных классов.

Предисловие.


Не так давно я перешел на свободный фреймворк вместо платного Adobe Flash. Им оказался Eclipse IDE + Flex SDK. Эта связка используется многими разработчиками-профессионалами и имеет множество преимуществ, одним из которых является полная бесплатность — несомненно плюс для тех, кто не хочет платить сотню долларов на программное обеспечение.
Eclipse удобен тем, что он расширяем за счет плагинов, что позволяет превратить его в полноценную среду разработки AS3-приложений.
О подробностях установки я расскажу в следующих постах.
В этом уроке я предложу только код с комментариями, а запуск приложения во Flash IDE можно найти в предыдущих уроках.

Переходим к делу.


Полноценное Flash-приложение на AS3 состоит из множества различных классов, так или иначе создающих работу приложения. Так делать гораздо удобнее и выгоднее, чем создавать огромный базовый класс из тысяч строк.
Создадим 2 класса, один из которых будет базовым (CustomTimer.as) и отдельный, создающий кнопки (Btn.as).
CustomTimer.as:
package
{
import flash.display.*;
import flash.events.*;
import flash.text.*;
import flash.utils.*;

import flashx.textLayout.accessibility.TextAccImpl;

public class CustomTimer extends Sprite
{
private var time:TextField; //поле для ввода времени
private var goBtn:Btn; //экземляр класса Btn, кнопка запуска таймера
private var txtFormat:TextFormat; //форматирование текстовых полей
private var timer:Timer; //главный таймер
private var count:TextField; //поле, где выводится оставшееся время
private var restartBtn:Btn; //кнопка запуска нового таймера
private var header:TextField; //заголовок
private var typeBtn:Btn; //кнопка типа ввода

private var minutes:Number = 0; //количество введенных пользователем минут
private var seconds:Number = 0; //количество введенных пользователем секунд
private var type:int = 1; // прим. (1)

public function CustomTimer()
{
createScene();
}
private function createScene():void { //создаем главную сцену
txtFormat = new TextFormat(); // прим. (2)
txtFormat.font = "_sans"; //шрифт без засечек
txtFormat.color = 0x000000;
txtFormat.size = 14;
txtFormat.align = TextFormatAlign.CENTER; //форматирование по центру

time = new TextField();
time.text = "5"; //дефолтное время
time.setTextFormat(txtFormat);
time.defaultTextFormat = txtFormat;
time.type = TextFieldType.INPUT; //тип поля — вводимый
time.border = true;
time.width = 200;
time.height = 20;
time.x = stage.stageWidth/2-time.width/2;
time.y = stage.stageHeight/2-time.height/2;
time.restrict="0-9"; //символы, которые можно ввести в текстовое поле
addChild(time);

txtFormat.size = 45;
header = new TextField();
header.text = "Таймер";
header.setTextFormat(txtFormat);
header.selectable = false; //текст выделить нельзя
header.width = stage.stageWidth;
header.x = 0;
header.y = stage.stageHeight/2-header.height/2-50;
addChild(header);

goBtn = new Btn();
goBtn.label("Создать"); //Методы "label" и "setCoord" созданного класса Btn
//будут рассмотрены ниже
goBtn.setCoord(stage.stageWidth/2-goBtn.width/2,
stage.stageHeight/2-goBtn.height/2+50);
addChild(goBtn);
goBtn.addEventListener(MouseEvent.CLICK, setTime);

typeBtn = new Btn();
typeBtn.label("sec");
typeBtn.setSize(27,17);
typeBtn.setCoord(time.x+time.width+10, time.y+2);
addChild(typeBtn);
typeBtn.addEventListener(MouseEvent.CLICK, setType);

}

private function setType(e:MouseEvent):void {
if (typeBtn.getLabel()=="sec") { //меняем надпись на другую
typeBtn.newLabel("min");
type = 2;
} else {
typeBtn.newLabel("sec");
type = 1;
}
}
private function setTime(e:MouseEvent):void {
createTimer();
}
private function createTimer():void {
var timeCount:Number = Number(time.text); //введенное пользователем время

txtFormat.size = 25;
txtFormat.align = TextFormatAlign.CENTER;

count = new TextField();
count.selectable = false;
count.y = stage.stageHeight/2;
count.width = stage.stageWidth;
count.height = 35;
count.setTextFormat(txtFormat);
count.defaultTextFormat = txtFormat;
addChild(count);
removeChild(time); //удаляем элементы сцены
removeChild(goBtn);
removeChild(header);
removeChild(typeBtn);

if (type==1) { //прим. (3)
minutes = int(timeCount/60);
seconds = timeCount - minutes*60;
} else {
minutes = timeCount;
}

update(); //функция обновления поля count

timer = new Timer(1000); //1000мс = 1сек.
timer.start();
timer.addEventListener(TimerEvent.TIMER, timerListener);
}

private function update():void {
count.text = "Осталось: " + String(minutes)+" минут " + String(seconds)
+ " секунд" ;
}

private function timerListener(e:TimerEvent):void {
if (seconds>0) {//уменьшаем секунды
seconds--;
update();
} else {
seconds = 59; //если секунды закончились, переходим на новую минуту
minutes--;
update();
}
if (minutes==0 && seconds==0) { //время вышло
final();
}
}
private function final():void {
timer.stop();

count.textColor = 0xFF0000;
count.text = "Время вышло!";

restartBtn = new Btn();
restartBtn.label("Новый");
restartBtn.x = stage.stageWidth/2-restartBtn.width/2;
restartBtn.y = count.y+50;
addChild(restartBtn);

restartBtn.addEventListener(MouseEvent.CLICK, restart);
}

private function restart(e:MouseEvent):void {

removeChild(restartBtn);
createScene();
count.text = "";
}

}
}

Примечания к коду.
1. Переменная type — тип вводимых данных. Определяет, в минутах или секундах ввел время пользователь. Кнопка typeBtn показывает текущий тип. Например, если на кнопке написано "sec" и в поле введено "5", то таймер будет отсчитывать 5 секунд. При нажатии на кнопку тип сменяется и таймер уже будет отсчитывать 5 минут.
2. Класс TextFormat определяет форматирование текстового поля, к которому этот формат назначен. С его помощью можно установить шрифт, размер, цвет, выравнивание и многое другое. Чтобы применить данный формат к текстовому полю, нужно вызвать метод setTextFormat(). Если же текстовое поле будет менять находящийся в нем текст, то нужно установить также свойство defaultTextFormat.
3. В этом участке кода мы определяем, сколько минут и сколько секунд ввел пользователь. Если выбран тип ввода секунд, то мы в минуты записывает число уместившихся минут, в секунды записываем оставшееся значение. Если же выбран тип ввода минут, то просто записываем в минуты данное число, а секунды оставляем равным 0.

Осталось только написать класс Btn.
Btn.as:
package
{
import flash.display.Sprite;
import flash.events.*;
import flash.text.*;
import flash.ui.*;

public class Btn extends Sprite
{
private var btn:Sprite;
private var txt:TextField;
private var format:TextFormat;

public function Btn() {
createBtn();
createFormat();
}
private function createBtn():void {
btn = new Sprite();
btn.graphics.beginFill(0x2A78C1); //оформление кнопки
btn.graphics.drawRoundRect(0,0,75,25,10,10);
btn.graphics.lineStyle(2);
addChild(btn);
btn.addEventListener(MouseEvent.MOUSE_OVER, over);
btn.addEventListener(MouseEvent.MOUSE_OUT, out);
}
public function label(lbl:String):void { //метод присваивания кнопке надписи
txt = new TextField();
txt.text = lbl;
txt.selectable = false;
txt.width = btn.width;
txt.height = btn.height;
btn.addChild(txt);

txt.setTextFormat(format);
txt.defaultTextFormat = format;

}

public function setSize(w:int, h:int):void { //метод присваивания кнопке размеров
btn.width = w;
btn.height = h;
}

public function setCoord(x:int, y:int):void { //метод присваивания кнопке координат
btn.x = x;
btn.y = y;
}

public function newLabel(newLbl:String):void { //метод обновления надписи
txt.text = newLbl;
}

public function getLabel():String { //возвращает текущую надпись кнопки
return txt.text;
}

private function over(e:MouseEvent):void {
Mouse.cursor = MouseCursor.BUTTON; //при наведении курсор — "рука"
}

private function out(e:MouseEvent):void {
Mouse.cursor = MouseCursor.AUTO; //автоматический
}
private function createFormat():void {
format = new TextFormat();
format.font = "Tahoma";
format.size = 14;
format.color = 0xFFFFFF;
format.align = TextFormatAlign.CENTER;

}
}
}

Этот класс — уникальный. Один раз написав такой класс, его можно использовать в других проектах, чтобы экономить время. В приложении у нас 3 различных кнопки, поэтому лучше использовать отдельный класс.
Пара слов об открытых методах класса. Методы с атрибутом public могут использоваться в других классах связанного приложения. Так например в базовом классе мы используем вышеперечисленные методы для изменения внешнего вида кнопки или возвращения каких-то ее свойств.
Использование методов setSize и setCoord позволяет сэкономить строки кода, а getLabel используется для того, чтобы код узнал, какая надпись в данный момент на кнопке (в частности, "sec" или "min").

Все, сохраним классы в одной директории и запустим. Приложение готово и можно использовать!

[swfobj src="http://cyber-page.ru/wp-content/uploads/2011/05/CustomTimer.swf"]

0 коммент.:

Отправить комментарий