Июнь 1st, 2010 от graann

Танцы с бубном, описанные в прошлом посте не актуальны для SDK 3.5 и выше :)

Март 30th, 2010 от graann

В ходе работы с пиккером, мы столкнулись с его неприятной особенностью: при попытке заменить предустановленный цвет пиккера на черный (самый первый элемент таблицы пиккера) контролл аккуратно закрывался, но и только. Т.е событие change не диспатчилось и текущий цвет не менялся.

В чем же проблема?

У стандартного пиккера предустановлена коллекция отображаемых в таблице цветов. Она передается в дата провайдер и содержит в себе 240 цветовых квадратов. Отображаемые в таблице цвета можно регулировать путем замены или модификации этой коллекции.

Для управления выбранным цветом контролла предусмотрено 2 свойства: selectedIndex selectedColor. Очевидно что selectedIndex — индекс цвета в коллекции дата провайдера. А вот с selectedColor все не так однозначно. При всем изобилии, таблица пиккера не вмещает в себя все могущие прийти в голову дизайнера цвета. И, когда вы пытаетесь в качестве selectedColor указатиь пиккеру значение отсутствующее в коллекции дата провайдера, происходит следующее.

* selectedColor устанавливается в заданный цвет
* В дата провайдере осуществляется поиск индекса итема содержащего этот цвет.
* Если такой итем найден, в selectedIndex прописывается соответствующее значение.
* Если же в дата провайдере отсутствует данный цвет, selectedIndex не изменяется.

Следует отметить, что по умолчанию selectedIndex и selectedColor выставлены в 0. Т.е когда мы пытаемся установить selectedColor в цвет отсутствующий в коллекции, selectedIndex не меняется и остается равным 0. В момент же интерактивного выбора нужного цвета в пиккере на каком-то из этапов осуществляется проверка соответствия индекса выбираемого значения текущему. Если значения совпадают, ничего не происходит. Отсюда и этот прекрасный баг. В selectedIndex-е пиккера прямо указано, что цвет у нас черный. А вот значение selectedColor при этом совершенно никого не волнует

Что делать?

Решение очевидно. Надо добавить в коллекцию дата провайдера недостающий цвет.

Вот так выглядит стандартный пиккер

Так он будет выглядеть если добавить новый цвет в конец коллекции.

Не слишком симпатично. Поэтому я предлагаю обратить внимание на второй столбец цветовой палитры. Он совершенно черный. Нехитрые исследования предустановленной коллекции дата провайдера показали, что перед нами столбец нулевых значений.

Для чего он, мне понять не удалось. А раз так, ничто не мешает добавлять в него новые цвета.

Нулевые элементы палитры начинаются с 1 индекса и повторяются через каждые 20, вплоть до 221 индекса.

Все что нужно это:
* Проверить значение selectedIndex после установки selectedColor.
* Если индекс не изменился, ищем первый нулевой элемент коллекции и присваиваем ему значение нового цвета.
* Если нулевые значения кончились добавляем новый цвет в конец коллекции.

Ниже код и превью результата

Code:

package
{
  import mx.collections.ListCollectionView;
  import mx.controls.ColorPicker;
 
  public class ChartColorPicker extends ColorPicker
  {
    public function ChartColorPicker()
    {
      super();
    }
    
      override public function set selectedColor(value:uint):void
      {
        
        if(dp && !dp.contains(value))
        {
          var ind: int = findFirstEmptyItemIndex();
          if(ind == -1) dp.addItem(value);
          else dp.setItemAt(value, ind);
        }
        super.selectedColor = value;
      }     
      
      private function get dp(): ListCollectionView
      {
        if( dataProvider is ListCollectionView) return dataProvider as ListCollectionView;
        else return null;
      }
      
      private const FIRST_EMPTY_INDEX: int = 1;
      private const EMPTY_INDEX_SHIFT: int = 20;
      
      private function findFirstEmptyItemIndex(): int
      {
        if(!dp) return -1;
        
        for(var i: int = FIRST_EMPTY_INDEX; i<dp.length; i+=EMPTY_INDEX_SHIFT)
        {
          if(dp.getItemAt(i) == 0)
          {
            return i;
          }
        }
        return -1;
      }
  }
}
Январь 31st, 2008 от graann

Путь скинизации посредством css тернист и многотруден. Особенно если каждый стиль требуют собственных скинов для виджетов (иконок, кнопок и т.д). Предположим нам надо подгрузить картинку. Для примера создадим класс наследованный от UIComponent и требующий подгрузки картинки описанной в css. Назовем класс Example.as.

Стили для него описаны в одноименном блоке стиля. (вы разумеется знаете, что стили цепляются к одноименной компоненте автоматом и не требуют каких-то дополнительных директив?)

Казалось бы чего проще?…

XML:

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" xmlns:ns1="src.*">
    <!−− так конечно делать не надо, но для примера покатит :) с css будет так же!−−>
    <mx:Style>
        Example{image: Embed("graphics/image.png");}
    </mx:Style>
    <ns1:Example x="42" y="24"/>
</ns1:Example></mx:Application>
  1. package src
  2. {
  3.        import mx.core.UIComponent;
  4.        import mx.controls.Image;
  5.  
  6.        public class Example extends UIComponent
  7.        {
  8.                private var image: Image;
  9.                
  10.                public function Example()
  11.                {
  12.  
  13.                }
  14.                
  15.                override protected function createChildren(): void
  16.                {
  17.                        super.createChildren();
  18.                        image=new Image();
  19.                        image.source=getStyle("image");
  20.                        addChild(image);
  21.                }
  22.                
  23.        }
  24. }

И после компиляции картинку благополучно не видим. Почему? Потому, что по умолчанию ее размеры составляют 0 x 0. Для того чтобы она отобразилась корректно требуется задать ей реальные размеры, каковые нам любезно предоставляют свойства measuredWidth и measuredHeight. Однако актуальные значения ширины и высоты будут доступны только после вызова метода protected function measure(): void UIComponent, о котором доступна подробная информация в хелпе.

Ну и собственно результат:

  1. package src
  2. {
  3. import mx.core.UIComponent;
  4. import mx.controls.Image;
  5.  
  6. public class Example extends UIComponent
  7. {
  8.         private var image: Image;
  9.        
  10.         public function Example()
  11.         {
  12.         }
  13.                
  14.         override protected function createChildren(): void
  15.         {
  16.                 super.createChildren();
  17.                 image=new Image();
  18.                 image.source=getStyle("image");
  19.                 addChild(image);
  20.         }
  21.  
  22.         override protected function measure():void
  23.         {
  24.                 super.measure();
  25.                 image.setActualSize(image.measuredWidth, image.measuredHeight);
  26.         }
  27.        
  28. }

Следует отметить, что подобных проблем с размерами не возникает в mxml-e.

Август 16th, 2007 от graann

По ряду причин была вынуждена установить на свою рабочую машину Vista. Расскажу о тех проблемах, с которыми столкнулась в ходе установки flex builder2 под Vista. Сразу оговорюсь переходить на 3-й builder мы не стали т.к он бета и показался нам не стабильным.

Проблема раз. Попытка установить второй билдер под eclipse 3.3:

Проблема два. Вернее легкое неудобство. В процессе установки инсталятор отказался демонстрировать контролы. Просто не отображал. Устанавливать пришлось на автопилоте руководствуясь подсознанием. Установила. Честно признаюсь не с первого раза.

Update установила.

Проблема три. SVN отказался дружить с подцепленым проектом. Проблема довольно специфическая, врядли у кого-то повторится, поэтому подробно останавливаться на ней не буду. Починила.

Установила subclips.

Последняя капля. Эклипс периодически вылетал с предупреждением следующего вида

В debugg-режиме с прерываниями он вылетал постоянно. Переставляла builder и java. Не помогло.

Июнь 5th, 2007 от graann

При большом количестве меток (да и вообще компонент) и частой их отрисовке вы непременно столкнетесь с тормозами. В случае с метками есть альтернатива в лице mx.core.UITextField, которой и посвящен этот пост. Что нас привлекает в mx.controls.Label? Возможность отобразить некий текст и применить к нему стили. UITextField нам эти возможности предоставляет так же. Однако есть одна тонкость. Как работать со стилями если:

public function setStyle(styleProp:String, value:*):void - Does nothing. A UITextField cannot have inline styles.

Не очень понятно зачем вообще нужен этот метод если он ничего не делает. Была мысль, что он описан в каком-то из имплементящихся интерфейсов, но подтверждения этому в коде найти не удалось. Впрочем я отвлеклась. Ну так как же работать со стилями? Да в общем точно так же, только через свойство styleName.

styleName:Object [read-write] - The class style used by this component. This can be a String, CSSStyleDeclaration or an IStyleClient.
Т.е uiTextField.styleName.setStyle("color", 0xff0000); сработает, но только если к UITextField уже был применен какой-то стиль. Не поленилась написать небольшой пример:

XML:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
import mx.core.UITextField;
import mx.styles.*;
 
private var uiTextField: UITextField;
 
override protected function createChildren(): void
{
  super.createChildren();
  uiTextField=new UITextField();
  addChild(uiTextField);
  uiTextField.text="mx.core.UITextField";
  trace("uiTextField.styleName: "+uiTextField.styleName);
// uiTextField.styleName: null
  var styleCss:CSSStyleDeclaration = new CSSStyleDeclaration();
  styleCss.setStyle('fontSize', 15);
  styleCss.setStyle('color', picker.selectedColor);
  uiTextField.styleName=styleCss;
}
 
public function changeColor(): void
{
  uiTextField.styleName.setStyle("color", picker.selectedColor);
}
 
]]>
</mx:Script>
<mx:ColorPicker id="picker" change="changeColor()" />
</mx:Application>
Апрель 3rd, 2007 от graann

В одном из предыдущих постов я рассказывала о решении проблемы пропадающих DataTip-ов в LineSeries с нефильтрованными данными (т.е filterData=false).
Как я уже говорила проблема в строке 969 класса mx.charts.series.LineSeries.as:

if (!isNaN(v.yFilter) && !isNaN(v.xFilter))

Не буду приводить исходный код тут. Слишком много букв.
При наследовании мне пришлось не только переопределить findDataPoints, но и воспроизвести приватный метод серии formatDataTip. Фактически же изменения коснулись только findDataPoints. Я добавила ряд проверок, однако оказалось что это был не лучший выход. Здесь народ столкнулся с аналогичной проблемой и нашел гораздо более удачное, на мой взгляд, решение. В findDataPoints они избежали многочисленных проверок заменив вышеупомянутую строку

if (!isNaN(v.yFilter) && !isNaN(v.xFilter)) на
if (!isNaN(v.yNumber) && !isNaN(v.xNumber)).

Март 26th, 2007 от graann

В процессе работы над очередным проектом у нас с Junik возникла потребность в использовании каскадных стилей. Подробнее о стилях и вариантах их использования написано тут, методика подгрузки css в рантайме тут, здесь же речь пойдет о тех проблемах с которыми мы столкнулись в процессе подгрузки файла css на стадии компиляции.
В окне свойств каждого проекта есть вкладка именуемая Flex Compiler, где в строке additional compiller arguments можно задавать опции для компиляции приложения. В перечне присутствует такая незаменимая в нашем случае опция как defaults-css-url. Собственно эту, как и все остальные, опцию можно вынести и в специальный конфигурационный xml. Хотя сейчас не об этом. Сейчас о том, что где бы вы ни задали ваш css вовсе не факт что он у вас заработает. Нам как раз посчастливилось столкнуться с этой проблемой. Изначально наш css подгружался в mxml-ине посредством тега Style и все прекрасно работало. После того как мы вынесли css в конфигурационный файл приложение работать напрочь отказывалось и постоянно генерило ошибки в рантайме.
В хелпе ничего внятного мы не нашли. Нечто отдаленное покоится тут Активное прогугливание ответов на вопрос “что за фиг?!” тоже нам не доло. Кроме криков о помощи еще кучки товарищей различных национальностей гугл ничем не порадовал.
Пришлось думать самим. Суть проблемы на поверку оказалась в следующем:
Как вы вероятно знаете, по умолчанию флекс пользуется услугами default.css. (у меня c:\Program Files\Adobe\Flex Builder 2\Flex SDK 2\frameworks\defaults.css) в котором аккуратно прописывает все стили компонент. Когда вы подгружаете css в теге Style приложение первоначально грузит вышеупомянутый defaults.css и только после этого применяет к приложению правила из вашего css. В случает же когда вы прописываете defaults-css-url defaults.css замещается вашим файлом и приложению просто не хватает стилей для отображения.

Февраль 7th, 2007 от graann

При работе с чартингом, одной из осей которого является DateTimeAxis, часто возникает потребность в изменении формата отображения меток. Как я поняла в ходе общения с кодом DateTimeAxis, сам флекс не меняет формат даты в зависимости от локали. По умолчания дата отображается в формате m/d/yy. Для российского глаза такое отображение несколько непривычно. Хелп предоставляет два пути решения этой проблемы.
1. labelFunction:Function [read-write]
Called to format axis values for display as labels. A labelFunction has the following signature:

  1. function labelFunction(labelValue:Object, previousValue:Object, axis:IAxis):String


If you know the types of the data your function will be formatting, you can specify an explicit type for the labelValue and previousValue parameters.

Казалось бы вот оно счастье, однако поспешность в выборе может послужить для вас причиной дополнительного геморроя. Качественная замена функции дело довольно муторное. Ведь интервал между метками может составлять как секунды так и годы. Куча кода. Рекомендую с негодованием отвергнуть эту веселую перспективу и обратить свой взор к пункту 2.

2. В хелпе есть такое понятие как Protected Methods. Для человека пришедшего из AS2 и не озаботившегося ознакомлением с матчастью AS3 такое буквосочетание может показаться слабо информативным, однако белые люди сжевавшие в процессе общения с флексом уже не одну pdf-ную страницу в курсе что Protected Methods - методы класса которые можно переопределять в наследниках. Часто большинство этих методов скрыто в недрах хелпа в аккордеоне с надписью “Show Inherited Protected Methods", однако это не наш случай. Интересующие нас сейчас методы DateTimeAxis на виду:

  1. formatDays(d:Date, previousValue:Date, axis:DateTimeAxis):String
  2. formatMilliseconds(d:Date, previousValue:Date, axis:DateTimeAxis):String
  3. formatMinutes(d:Date, previousValue:Date, axis:DateTimeAxis):String
  4. formatMonths(d:Date, previousValue:Date, axis:DateTimeAxis):String
  5. formatSeconds(d:Date, previousValue:Date, axis:DateTimeAxis):String
  6. formatYears(d:Date, previousValue:Date, axis:DateTimeAxis):String

Разумеется прежде чем переопределять их в соответствии с вашими пожеланиями следует ознакомиться с исходным кодом DateTimeAxis. Там за вас уже все придумали и написали:

  1. protected function formatYears(d:Date, previousValue:Date, axis:DateTimeAxis):String
  2. {
  3.         var fy:Number = d[fullYearP];
  4.         return fy.toString();
  5. }
  6. protected function formatMonths(d:Date, previousValue:Date, axis:DateTimeAxis):String
  7. {
  8.         var fy:Number = d[fullYearP];
  9.         return (d[monthP] + 1) + "/" + ((fy % 100) < 10 ? "0" + fy % 100 : fy % 100);
  10. }
  11. protected function formatDays(d:Date, previousValue:Date, axis:DateTimeAxis):String
  12. {
  13.         var fy:Number = d[fullYearP];
  14.         return (d[monthP] + 1) + "/" + d[dateP] + "/" + ((fy % 100) < 10 ? "0" + fy % 100 : fy % 100);
  15. }
  16. protected function formatMinutes(d:Date, previousValue:Date, axis:DateTimeAxis):String
  17. {
  18.         return d[hoursP] + ":" + (d[minutesP] < 10 ? "0" + d[minutesP] : d[minutesP]);
  19. }
  20. protected function formatSeconds(d:Date, previousValue:Date, axis:DateTimeAxis):String
  21. {
  22.         return d[hoursP]+ ":" + (d[minutesP] < 10 ? "0" + d[minutesP] : d[minutesP]) + ":" + (d[secondsP] < 10 ? "0" + d[secondsP] : d[secondsP]);
  23. }

Потребуется только слегка откорректировать эти методы в соответствии с вашими пожеланиями. Или, если приложение требует некоторой гибкости, добавить к уже имеющемуся формату еще несколько форматов отображения. (в зависимости от локали)

Кстати. Если вдруг получившиеся в ходе переопределения методов метки будут натыкаться друг на друга и делать подписи абсолютно нечитаемыми следует воспользоваться методом reduceLabels(intervalStart:AxisLabel, intervalEnd:AxisLabel):AxisLabelSet, а никак не свойством interval : Number, как это может захотеться с первого взгляда. Но это уже совсем другая история…

Декабрь 11th, 2006 от graann

Flex Stress Testing Framework
The information in this article can help you start load testing your own Flex Data Services applications.

Декабрь 1st, 2006 от graann

:: Следующие >>

Graann`s blog
flash, flex и все, что придет в голову

Сентябрь 2010
Пн Вт Ср Чт Пт Сб Вс
 << <   > >>
    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      

О блоге

С назначением блога можно ознакомиться здесь

Идейным вдохновителем и по совместительству куратором блога является Сonstantiner, за что ему огромный респект и уважуха! Впрочем не только за это :)

Поиск

powered by b2evolution free blog software


Design downloaded from Zeroweb.org
Website templates, layouts, and website tools for FREE!
Free short URL services from urlSNIP.