Archive

Archive for the ‘FLEX’ Category

Własny renderer dla DataGrid (FLEX)

September 26th, 2009 No comments

Adobe FLEX posiada komponent do wyświetlania tabelek który nazywa się DataGrid. W komórce tabeli możemy wyświetlić tekst, tekst HTML lub inny prosty komponent. Mi jednak tego było mało. Postanowiłem więc napisać swój własny renderer dla komórek tabeli. Z początku wydawało mi się to proste: napiszę nową klasę dziedziczącą po DataGridItemRenderer i w niej upakuję logikę do wyświetlania mojej komórki tabeli. Niestety rzeczywistość okazała się niezwykle zagmatwana i zmusiła mnie do dokopania się do nieprzyzwoitych paskudztw ukrytych wewnątrz FLEX.

Nie mogłem zrobić klasy pochodnej z DataGridItemRenderer, gdyż tak klasa dziczy po UITextField czyli potrafi wyświetlać tekst. A ja potrzebowałem tekst i coś jeszcze. Spróbowałem więc pisać na płótnie Canvas. Okazało się, że Canvas prawie działa. Problemem były wartości, które poprzez interfejs IDataRenderer otrzymywała moja klasa: zamiast spodziewanego obiektu reprezentującego konkretną komórkę tabeli otrzymywałem obiekt reprezentujący cały wiersz. Zastanowiło mnie też dlaczego klasa Canvas – czyli obiekt reprezentujący płótno implementuje interfejs IDataRenderer – może Wy widzicie związek? Dla mnie to tak jak mercedes standardowo wyposażony w pieska kiwającego głową.

Analizując przykłady, odkryłem że klasa CheckBox powinna zachowywać się w tej materii właściwie, czyli gdy chciałem aby komórka tabeli była wyświetlana obiektem klasy CheckBox – to obiekt ten otrzymywał dane reprezentujące konkretną komórkę a nie cały wiersz. To mnie zastanowiło, dlaczego Canvas dostaje do wyświetlenia wiersz a CheckBox dostaje wartość komórki. Pomyślałem, że problem leży gdzieś w interfejsach. Pomyślałem sobie, że może DataGrid wpisując dane do komórek swojej tabeli sprawdza – czy klasa odpowiedzialna za wyświetlenie tej komórki implementuje wskazany interfejs – i w zależności od tego wysyła do nie odpowiednie dane. To by brzmiało rozsądnie. Niestety, debugger nie potwierdził moich przeczuć.

Zajrzałem więc do źródła CheckBox i oto co znalazłem. Jest tam sobie funkcja setter na pole data wymagana przez interfejs IDataRenderer. Oto ona:

W moim odczuciu, to nie wygląda jak zwykły setter. Dla mnie to wygląda jak na kod zepsutego projektu. Taka napisana funkcja zachowuje się w sposób nieprzewidywalny. W dodatku, po co ktoś projektował interfejs skoro większość klas FLEXa go odziedziczy?

Wracając do sprawy, aby napisać własną klasę służącą do wyświetlania komórek tabeli powinniśmy zaimplementować interfejsy: IDataRendererIDropInListItemRenderer. Aby dostać wartość wiersza potrzebny jest nam IDataRenderer, jednak ten interfejs implementują prawie wszystkie komponenty FLEXa. Aby dobrać się do wartości komórki, potrzebujemy IDropInListItemRenderer. Możemy do zrobić na przykład tak:

Martwię się o FLEX. To wspaniała technologia, która umożliwia tworzenie wspaniałych rzeczy. Jednak bałagan który w niej panuje może być dla tej niej zabójczy. Bałagan, o którym wie każdy programista, który programował w FLEX. Bałagan oczywiście zawsze towarzyszy pracy programistów, jednak w niektórych projektach jest czasami nie do zniesienia.

Categories: FLEX Tags:

RTMP jak to robi YouTube

July 6th, 2009 3 comments

Z protokołem RTMP jest związany pewien problem. Standardowo działa on na porcie 1935. Właściwie, to nie jest problem z protokołem RTMP ale z ISP. Firmy, które sprzedają nam Internet lubią filtrować i kolejkować pakiety. Dlatego połączenia na porcie 1935 – który jest mało znany w Internecie działają dużo gorzej niż połączenia na porcie 80. Adobe wiedziało o tym, i wprowadziło protokół RTMPT, który jest opakowaniem protokołu RTMP w protokół HTTP, który działa na porcie 80 i który może doprowadzić do połamania języka.

YouTube zrobił coś innego. Otóż, You Tube ma w sobie coś takiego jak nagrywanie z kamery webowej. Do tego celu używają protokołu RTMP. Jednak wydaje mi się, że na porcie 80. Powiedział mi to NetLimiter – skąd inąd fajny program który polecam.

Postanowiłem więc dokładnie sprawdzić czy na pewno jest to protokół RTMP – na co wyglądało, czy też może zwyczajnie RTMPT. Zanurkowałem głęboko w system a jako butli tlenowej użyłem Wireshark. Wireshark to program który umożliwia podglądanie danych przekazywanych w połączeniach sieciowych. Chciałem sprawdzić, co tam się przesyłam z mojego komputera na serwery YouTube. Gdyby był to protokół RTMPT to podczas nagrywania wideo znalazło by się tam sporo żądań POST. Nie było ich… Było za to coś takiego:

rtmp://…:80/ – na 99% YouTube korzysta z protokołu RTMP na porcie 80.

Dotychczas z serwerem Red5 łączyłem się na porcie 1935 po protokole RTMP. Jeżeli połączenie działało źle – to próbowałem przełączyć się w na połączenie RTMPT na porcie 80 – sterowałem tym ręcznie lub pozwalałem aby Flash robił to automatycznie. Być może nie potrzebnie, skoro YouTube używa RTMP na porcie 80 to ja też powinienem spróbować.

 

 

Categories: FLEX Tags:

Marilena czyli Flex i wyszukiwanie twarzy

March 30th, 2009 No comments

Odkryłem dziś nową interesująca bibliotekę dla Adobe Flex – Marilena. Z pomocą tej biblioteki Flash Player może rozpoznać położenie twarzy w obrazie, na przykład w obrazie z kamery.

Ten przykład działania biblioteki Marilena pochodzi z bloga François Tarlier.

Przyspieszoną wersję biblioteki można znaleźć na blogu quasimondo. Tam też można znaleźć kolejne demo – krzywe zwierciadło.

Inne fajne przykłady można znaleźć na stronie mr.doob (o ile Unia Europejska mu nie zabroni się tak nazywać). Warto też zerknąć do źródeł projektu pana doob.

Categories: FLEX Tags:

Sterowanie aplikacjami Flash przy użyciu kamery internetowej

February 27th, 2009 6 comments

Dziś, na spotkaniu ASCUG poznałem nową technologię służącą do sterowania aplikacjami Flash za pomocą kamery internetowej. Podziękowania dla Błażeja Modżejewskiego z Flashmind za interesującą prezentację. Aby sterować aplikacją za pomocą kamery internetowej, trzeba przetwarzać obraz z kamery i wyszukiwać w nim pewne wzorce. W programie FMT definiujemy wskazujemy kolorowy znacznik, którego rozpoznanie w obrazie z kamery steruje aplikacją. Jest to proste i właśnie dzięki temu może być bardzo dobrą alternatywą dla zaawansowanej technologii FLARToolKit. FLAR potrzebuje wykonać dużo więcej operacji i dla tego w praktyce może działać zbyt wolno.. Czekam na informacja o sposobie licencjonowania biblioteki FMT.

Categories: FLEX Tags:

FLARToolKit czyli analiza obrazu w technologii Flash

February 4th, 2009 8 comments

Jak podaje Adobers właśnie pojawiła się technologia służąca do wyszukiwania wzorców w obrazie. Biblioteka napisana jest w języku programowania Aciton Script 3, co oznacza, że będzie działać w przeglądarce internetowej, i że będę mógł jej używać w swoich projektach Flash / Flex. Biblioteka jest za darmo dostępna jest na licencji GPL, co oznacza, że programy z niej korzystające też będą musiały być GPL.

Dzięki bibliotece FLARToolKit program uruchomiony w przeglądarce internetowej może wykryć wzorzec w obrazie. Na przykład ten który wydrukowałem na kartce i z powodu zajętości rąk musiałem przytrzymać w paszczy. Bardzo się cieszę, bo biblioteka FLARToolKit otwiera przede mną nowe możliwości w programowaniu aplikacji z których zamierzam korzystać.

Categories: FLEX Tags:

Flex, PreloadSwf – dziwny błąd

January 5th, 2009 No comments
Coś mi się zepsuło w Flex Builder 3.2. Moje projekty przestały się uruchamiać a na stronach internetowych wyskakiwał komunikat:
Error #2044: Nieobsługiwane securityError:. text=Error #2048: Naruszenie obszaru izolowanego: file:///C|%2FUsers%2FAntek%2FDocuments%2FFlex%20Builder%203%2F.metadata%2F.plugins%2Fcom.adobe.flash.profiler%2FProfilerAgent.swf?host=localhost&port=9999 nie może wczytać danych z localhost:9999.
 at ProfilerAgent()[C:\SVN\branches\3.2.0\modules\profiler3\as\ProfilerAgent.as:127]
Rozwiązaniem było edycja pliku: C:\Users\Antek\mm.cfg i zakomentowanie linii:
#PreloadSwf=C:/Users/Antek/Documents/Flex Builder 3/.metadata/.plugins/com.adobe.flash.profiler/ProfilerAgent.swf?host=localhost&port=999
Warto zwrócić uwagę, że parametr konfiguracyjny PreloadSwf nie jest udokumentowany. Ciekawe, ile nieudokumentowanych niespodzianek czeka mnie jeszcze w technologii Adobe?
Categories: FLEX Tags:

Flex i klasy prywatny

December 14th, 2008 No comments

Bardzo lubię korzystać z prywatnych zagnieżdżonych klas w języku Java. Niestety, nie potrafię ich znaleźć w Action Script. To duża strata dla języka programowania. To prawie tak, jakby w języku polskim nie było przymiotników;). Problemy, które chciałbym rozwiązać prywatną klasą rozwiązuję więc w Flex w następujący sposób. Tworzę nowy plik z klasą internal class. Rzeczy, które powinny być private robię jako “interna”. Czyli w Flex mam dwie klasy w osobnych plikach lecz jednej z nich używam jako prywatnej. Właściwości języka AS3 bronią mnie przed użyciem moje klasy prawie prywatnej poza pakietem. Na przykład:

    public interface INetStreamClient

    {

 

        function onMetaData(info:Object=null):void;

[…]

        

Czy ktoś lubi dynamiczne klasy do implementowania netStream.client – bo ja nie… (takie dynamiczne klasy wymagają zbyt wielu komentarzy). Dlatego stworzyłem ten interfejs z wszystkimi metodami zwrotnymi serwera. Następnie każda implementacja rozszerza ten interfejs. Domyślna implementacja to logowanie:

    public class TracerNetStreamClient implements INetStreamClient {        

        

        public function onMetaData(info:Object=null):void {

            trace(“NetStreamClient.onMetaData: “ + info + ” duration: “ + info.duration);

        }

[…]

 

Powoli dochodzę do sedna sprawy. Mam klasę która pomaga mi odtwarzać filmy. Jednym z pól tej klasy jest “INetStreamClient”. W aplikacji jakieś inne obiekty mogą używać mojego pomocnika do odtwarzania filmów, podając mu swoja implementację klienta strumieni. Więc mam coś takiego:

    public class MoviePlayer

    {

        [Inspectable]

        public var netStreamClient:INetStreamClient;        

        

        private function createNetStream():void {

            _netStream = new NetStream(netConnection);

            _netStream.client = new MoviePlayerNetStreamClient(this, netStreamClient == null ? new TracerNetStreamClient() : netStreamClient );            

[…]

I właśnie teraz bardzo mi zabrakło zagnieżdżonej klasy prywatnej. Chciałem wzbogacić działanie metody onMetaData. Potrzebuję klasy Proxy, której będę potrzebował tylko w tym miejscu, i która powinna mieć dostęp do prywatnych możliwości klasy MoviePlayer. Niestety w Flex tego nie ma. Dlatego radzę sobie na około tworząc klasy internal. Moje prywatne Proxy wygląda więc tak:

    internal class MoviePlayerNetStreamClient implements INetStreamClient {

 

        private var _moviePlayer:MoviePlayer;

        private var _netStreamClient:INetStreamClient;

        

        public function MoviePlayerNetStreamClient(moviePlayer:MoviePlayer,netStreamClient:INetStreamClient)

        {

            super();

            _moviePlayer = moviePlayer;

            _netStreamClient = netStreamClient;

        }

        

        public function onMetaData(info:Object=null):void {

            var d:Number = info["duration"];

            _moviePlayer.addDuration(d);

            return _netStreamClient.onMetaData(info);

        }

        

[…]

Jak widać, klasy prywatne mogą przydać się do implementacji wzorca projektowego dekorator. Ich brak kompensuję klasą internal. Klasa internal widoczna jest w obrębie pakietu i trzeba ją umieścić w osobnym pliku.

Categories: FLEX Tags:

Image + ProgressBar

October 14th, 2008 2 comments

Bardzo lubię technologie Adobe Flex gdyż można w niej pisać naprawdę szybko programy. Na przykład – potrzebuję indykatora postępu podczas ładowania obrazka. Mogę to zrobić w następujący sposób. Tworzę klasę pochodną od klasy odpowiedzialnej za wyświetlanie obrazka i definiuję metody przechwytujące zdarzenia postępu ładowania i wgrania całego obrazka. Łączę to z komponentem wyświetlania paska postępu i już. Wygląda to tak:

public class ImageWithProgressbar extends Image
{
  public function ImageWithProgressbar()
  {
    super();
  }
  
  private var _progressBar:ProgressBar;
  
  override protected function createChildren():void {
    super.createChildren();
    addEventListener(ProgressEvent.PROGRESS, progressHandler);
    addEventListener(Event.COMPLETE, completeHandler);
    _progressBar = new ProgressBar();
    _progressBar.mode = ProgressBarMode.MANUAL;
    _progressBar.percentWidth = 100;
    _progressBar.setStyle("horizontalCenter", "0");
    _progressBar.setStyle("verticalCenter", "0");
    addChild(_progressBar);
    _progressBar.visible = false;
    
  }
  
  private function progressHandler(e:ProgressEvent):void {
    _progressBar.setProgress(e.bytesLoaded,e.bytesTotal);
    _progressBar.visible = e.bytesLoaded < e.bytesTotal;
  }
  
  private function completeHandler(e:Event):void {
    _progressBar.visible = false;
  }
}

W efekcie otrzymuję klasę – która umożliwia wstawianie obrazków z paskiem postępu wyświetlanym podczas ładowania.

Categories: FLEX Tags:

Flex i automatycznie skalowane Canvas

July 30th, 2008 No comments

W technologii Adobe Flex jest coś takiego jak płótno – Canvas. Jeżeli na tym płótnie położymy zbyt wiele obiektów, to Flex automatycznie narysuje suwaki (ScrollBar). Ja zamiast suwaków wolę skalować. To znaczy, gdy położę na płótnie jakieś elementy które z niego wystają to Flex skaluje zawartość zamiast rysować suwaki. Zrobiłem to dość prosto.

package eu.jakubiak.ui
{
  import mx.containers.Canvas;
  import mx.core.ScrollPolicy;

  public class ScaledCanvas extends Canvas
  {
    public function ScaledCanvas()
    {
      super();
      horizontalScrollPolicy = ScrollPolicy.OFF;
      verticalScrollPolicy = ScrollPolicy.OFF;
    }
    
    override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void {
      super.updateDisplayList(unscaledWidth,unscaledHeight);
      var mx:Number = measuredWidth / scaleX;
      var my:Number = measuredHeight / scaleY;
      if(width < mx || height < my) {
        var sx:Number = width / mx;
        var sy:Number = height / my;
        if(Math.max(Math.abs(sy - scaleY),Math.abs(sx - scaleX))>0.01) {
          var s:Number = Math.min( sx, sy );
          this.scaleX = s;
          this.scaleY = s;
        } 
      } else if ( width > mx && height > my && ( scaleX != 1 || scaleY != 1 ) ) {
        scaleX = 1;
        scaleY = 1;
      }
    }
  }
}

Jest to użyteczne, gdy na przykład mamy koszyk z elementami przeciąganymi techniką drag&drop. Gdy włożymy do koszyka za dużo elementów to koszyk się pomniejsza zamiast rysować suwaki.

Categories: FLEX Tags:

H.264 dla Flash

April 23rd, 2008 No comments
O tym, że MPlayer rządzi pisałem już kilka razy. Przedstawiam najprostszy, znany mi sposób, konwersji filmów do formatu H.264, dla aplikacji internetowych napisanych w Flash:
mencoder film.avi -o film.mov -of lavf -lavfopts format=mov \
 -oac lavc -lavcopts aglobal=1:acodec=libfaac:abitrate=64 \
 -ovc x264 -x264encopts bitrate=500:qp_min=15:qp_max=51:qcomp=0.8:cabac:deblock:subq=7:keyint=250:frameref=6artitions=all:b_pyramid:8x8dct:global_header:me=umh \
 -srate 22050 -vf scale=640:-3 -sws 3 -ofps 24
Categories: FLEX Tags: