
Удобная вставка текста в текстовые поля кнопки
Это первый пост, потому хочется начать с чего-нибудь простого. Расскажу о функции, которая сильно упрощает мне жизнь при создании GUI.
Обычно это делается примерно так:
что не красиво и не эффективно
параметр _mc: DisplayObject, это может быть кнопка с текстовыми полями, MovieClip с глубоко внутри запрятанным текстовым полем или даже само текстовое поле.
параметр _text: String, строка которую нужно присвоить текстовым полям.
Пример использования:
Кроме того, если во Flash динамическому текстовому полю был присвоен параметр «жирный» то простое присвоение текста через поле .text эту жирность уберет. Используя эту функцию этой проблемы удасться избежать, то есть имеет смысл использовать ее и для присваивания текста в текстовое поле.
Согласно пункту 6 правил даю ссылку на эту статью на моем блоге.
Спасибо за внимание!
Лирическое вступление
Для формирования сложного GUI (например игрового) я почти всегда использую следующий способ: GUI формируется в fla файле (каждое окно — отдельный класс), всем кнопкам, текстовым полям и тп прописываются instance name, а затем окно или несколько экспортируется в swc, которые подключаются к проекту (например FlashDevelop), пишутся классы наследованные от классов втянутых из swc в которых я уже вношу текст на кнопки, привязываю обработчики событий, и вообще из шаблона делаю собственно GUI. Делая так я имею возможность импортировать макеты окон прямо из PSD файлов и быстро подключать их к проекту. Уверен что этот прием известен большинству flash-разработчиков, потому продолжим (если есть необходимость в статье об этом — скажите).Первая проблема
В процессе написания класса окна унаследованного от класса из swc часто возникает необходимость просто и быстро вписать текст в текстовое поле, являющее дочерним объектом не для самого окна, а например обернутое в один или несколько MovieClip-ов. Обычно такая ситуация решается одним из трех способов:- разработчик возвращается во fla файл и убирает ненужные обертки (часто этот способ самый правильный, хоть не всегда возможный)
- разработчик использует методы getChildAt, getChildByName
В результате присвоение текста выглядит примерно так
или и вовсе(((myWindow.getChildByName('myChildMovie') as Sprite). getChildAt(0) as Sprite). getChildByName('myTextfield') as Textfield).text='текст';
Это наиболее некрасивый и глючный способ.myWindow.getChildByName('myChildMovie').getChildAt(0). getChildByName('myTextfield').text='текст';
- разработчик для доступа к вложенному текстовому полю возвращается во fla и присваивает Class Name и Instance Name каждому вложенному MovieClip находящемуся в иерархии сцены между окном и текстовым полем а также Instance Name самому текстовому полю. В результате присвоение текста выглядит так
myWindow.myChildMovie.mySubChildMovie.myTextfield.text='текст';
Этот способ довольно громоздкий но в целом не плохой
Вторая проблема
Допустим в классе окна есть несколько дочерних кнопок, у которых в каждом состоянии есть динамическое текстовое поле, нам нужно каждой кнопке присвоить текст таким образом, чтобы он прописался во все текстовые поля состояний кнопки.Обычно это делается примерно так:
myButton.upState.getChildByName('myTextField').text="текст на кнопке";
myButton.overState.getChildAt(0).text="текст на кнопке";
myButton.downState.getChildByName('myTextField').text="текст на кнопке";
что не красиво и не эффективно
Решение
Представленная функция берет переданный ей DisplayObject и пробегает рекурсивно все его дочерние DisplayObject и каждому найденному текстовому полю присваивает переданный ей текст.параметр _mc: DisplayObject, это может быть кнопка с текстовыми полями, MovieClip с глубоко внутри запрятанным текстовым полем или даже само текстовое поле.
параметр _text: String, строка которую нужно присвоить текстовым полям.
public static function setTextToAllTextfields(_mc : DisplayObject,_text : String) : void
{
if (_mc is TextField)
{
var tf : TextField = _mc as TextField;
var format : TextFormat;
if (tf.text.length>0)
{
format = tf.getTextFormat(0, tf.text.length);
} else
{
format = tf.getTextFormat();
}
tf.text = _text;
// Это сделано для того чтобы после смены текста не исчезал TextFormat
//созданный через настройки текстового поля во Flash
tf.setTextFormat(format);
}
if (_mc is DisplayObjectContainer)
{
var mc : DisplayObjectContainer = _mc as DisplayObjectContainer;
for (var x : int = 0; x < mc.numChildren; ++x)
{
var child : DisplayObject = mc.getChildAt(x);
setTextToAllTextfields(child, _text);
}
}
if (_mc is SimpleButton)
{
var btn : SimpleButton = _mc as SimpleButton;
setTextToAllTextfields(btn.upState, _text);
setTextToAllTextfields(btn.overState, _text);
setTextToAllTextfields(btn.downState, _text);
}
}
Пример использования:
setTextToAllTextfields(myMovieClip,'Текст для всех вложеных текстовых полей');
setTextToAllTextfields(myButton,'Текст для всех состояний кнопки');
setTextToAllTextfields(myTextFileld,'Текст для текстового поля');
Кроме того, если во Flash динамическому текстовому полю был присвоен параметр «жирный» то простое присвоение текста через поле .text эту жирность уберет. Используя эту функцию этой проблемы удасться избежать, то есть имеет смысл использовать ее и для присваивания текста в текстовое поле.
Заключение
Удобно? Я считаю да. Но за все приходится платить и платим мы быстродействием. Потому не стоит применять эту функцию в узких местах программы. Однако открытие окна обычно узким местом не является и потому относительно медленное выполнение вставки текста не приведет к сколько-нибудь заметному подтормаживанию.Согласно пункту 6 правил даю ссылку на эту статью на моем блоге.
Спасибо за внимание!
- +9
- Troglodit
Комментарии (22)
Интересный подход. Глубокая иерархия вложенных мувиклипов — это, конечно, не слишком хорошо, но метод решения ты придумал элегантный, и рекурсия смотрится здесь приятно.
P.S. Очень клёвая аватарка :)
Вопрос: а про организацию кода целой игры, ни кто не писал?
только с потерей «жирности» можно бороться и передавая текст отформатированным, например так
также и цвет шрифта выставить можно
не мешало бы конечно сделать сам метод более «умным» — передавать имя текстового поля, у меня например в мувике может быть несколько текстовых полей =)
1.
Приведет к тому что в текстовом поле будут видны теги в виде текста, а чтобы был отрендерен html его надо присваивать не в свойство text а в свойство htmlText. Так же можно задавать в коде формат не через htmlText, а создавая новый TextFormat.
2. Всегда выставлять в коде формат руками для полей которым этот формат присвоен в html не рационально, тк вместо того чтобы сделать всю полировку окна во флеше а в коде только вставлять значения, мы начнем еще в коде заморачиваться видом текстовых полей. Это, к тому же, приведет к проблемам если нам понадобиться поменять макет окна. Тогда нам кроме втягивание нового вида окна во флеш надо будет не забыть и поменять формат текста в коде.
3. Можно действительно передавать имя текстового поля, но я предпочитаю в случае если мувик содержит не одно поле а несколько, все же поступать как описано в «пункте 3 первой проблемы». В этом случае на моей стороне мощь средств IDE — автоподстановка и контроль за динамическими свойствами (в FDT). А когда все кнопки и поля доступны автоподстановкой через точку, тогда запросто можно юзать эту фенкцию для одного единственного мувика или кнопки. Получается что имя текстового поля я просто выношу из скобок и делаю более багоустойчивым.
2. Так то оно так, но если у текстфилда одно слово выделено цветом к примеру, твой метод не пройдет — он ведь считает что весь текст в одном формате
3. Мне одному кажется подобное извратом myWindow.myChildMovie.mySubChildMovie.myTextfield.text='текст'?
а ведь можно было бы всего лишь передать имя текстфилда доп. параметром, вроде такого:
3. Ну тут на вкус и цвет. Я предпочитаю чтобы инстанснеймы строками не передавались, а контролировались компилятором, иначе опечатка = ошибка времени исполнения, а в моем случае это ошибка компиляции что куда удобней.
Согласен, на вкус и цвет все фломастеры разные =)
Ну и ещё — в любом случае используются все элементы такой вот иерархии. Каждый мувиклип. А если гдето в глубине один нужный — нужно перестраивать саму иерархию.
Надеюсь понятно написал)
достаточно использовать их в качестве графического представления и проблем с наследованием и расширяемостью не будет, по типу:
ИМХО так намного удобнее
потом встал после точки, контрол пробел и выбирай чайлды, myButton, myTextField и все другие у кого есть инстанс неймы. Не знал об этом?
1. это работает только с эмбед, захочешь грузить графику и такой код не заработает
2. таким образом все менюшки у тебя пишутся с нуля, я же могу сделать базовую менюшку в которой будут реализованы все базовые методы
3. наследовать класс от мувиклипа только для того чтобы можно было чуть удобнее добираться до элементов его представления — по мне так неправильно. Ошибку времени выполнения можно получить всегда ) тестировать нужно когда что либо выкидываешь ))
Я не претендую на единственно верный подход, просто описал свой подход