2008年9月2日 星期二

Error #2044: 未處理的 IOErrorEvent.. Error #2036

福克斯最近接到朋友的通知,發現福克斯之前寫的程式出現了『未處理的 IOErrorEvent』。天啊,這個問題在網路上也有超多人遇到的。

這個問題的主要來源是,呼叫 Loader.load 的時候,並沒有聽取 IOErrorEvent 的事件。當然,很多人都會說,沒有啊!我的都有聽。可是,每次到最後,證實出來都是沒有聽取。

當然,沒有聽取 IOErrorEvent 事件並不是整件事的原罪。會發生這個問題,最主要的原因有:1. 檔案找不到、2. 檔案壞掉、3. 其它原因導致檔案無法讀取。

所以啦,下次大家看到這個問題的時候,可以檢查是不是所有的 loader 都有聽取 IOErrorEvent 的事件。檢查完之後,別忘了,一定是程式出錯了,不然,不可能 Flash 會說『未處理的 IOErrorEvent』。

不過,話說回來,福克斯其實在 Flex 2 的時候,就已經發生過了。所以,福克斯一向養成聽取這個事件的好習慣。但是,為什麼福克斯的程式還是會有這個問題。最主要的原因是,福克斯使用了一個別人寫的 Flex 2 元件。然而,福克斯之前就以為,如果給它一個錯誤的網址,它能夠處理,或是 throw 一個 Error 出來。但是,實際上,並沒有。

ps 有一個很重要的事, Loader 這個類別是沒辦法直接聽取 IOErrorEvent,而是要用 Loader.contentLoader.addEventListener(...) 的方式。

2008年8月19日 星期二

Binding 的使用, part 1

Binding 是 Flex 中一個很特別的項目。許多傳統的程式語言中,大多都沒有類似的東西。說真的,福克斯認為,要設計一個非常易於使用的 Binding 並不是件容易的事。對福克斯來說,Flex 的 Binding 算是一個還算簡單,但還不夠直覺的方式。不過,經過幾次的使用,福克斯覺得 Binding 真的是一個很方便的工具。

最近,福克斯須要教同事,如何設計 Flex。當我們討論到 Binding 的時候,福克斯發現,這個觀念似乎對某些程式設計師來說,不容易被接受。一些 Flex 的設計師們可能會覺得,這麼好用的東西,怎麼可能會不容易接受。福克斯發現,不易被接受的原因並不是不好用,而是不夠直覺。說真的,Flex Binding 的設計可以算是目前不錯的設計。所以這一系列的文章,將會和大家一起討論,如何正確地使用 Binding 這項工具。

Binding 是指一個永遠成立的方程式,例如: objA.x = objB.y + n。此時,如果 objB.y 改變的時候,objA.x 也會跟著被修改。針對這種關係,在傳統的程式語言中(如 Java, C#, C++, JavaScript…等),我們必須要在 objB 中加入一個 event listener 用來聽取 y 修改的事件,進而重新計算方程式的結果。

Flex 的 Binding 也是使用同樣的設計方式。當我們在 Flex 中建立一個 Binding 時,Flex 會自動建立 event listener 並自動建立重新計算方程式的 function。

福克斯建議,第一次接觸 Binding 最好從最簡單的模式開始學習。所以,以下是完成 objA.x = objB.y 的 Binding 呼叫方式:

BindingUtils.bindProperty(objA, "x", objB, "y");

這段程式中,BindingUtils 是 mx.binding.utils package 中用來建立 Binding 的物件。最簡單使用 Binding 的方式,就是讓兩個物件的一個屬性互相連結在一起。以上面的這個例子來說,我們使用最簡單的方式,即 bindProperty 來連結兩個物件的屬性。我們可以直接以方程式 objA.x = objB.y 的方式來看,呼叫 BindingUtils.bindProperty 時,可以使用同樣的順序來呼叫。所以,我們可以直接將方程式的參數,直接代入 BindingUtils.bindProperty 之中。要特別注意的地方是,物件的 property 部份,都必須要以『字串』的方式輸入。




In Flex, the binding is made by BindingUtils and ChangeWatcher.

2008年8月8日 星期五

Autoresizing Canvas


Auto-resizing is a common feature in contemporary programming languages, but not Flex. It is uncommon. After surveying, I have to admit that I can't find it. So, I decide to write it by my own. 

The auto-resizing is based on the mouse position and dragging operation. The dragging operation can be observed by mouse down or drag start.  The mouse position can be observed by the mouse move event. But we won't be notified while the mouse is moved out side of canvas. Another way to be aware of mouse can be done by reading mouseX and mouseY in enter frame event, even if the mouse is moved out of canvas. 

The example program will be designed as:
1. using a boolean flag to record mouse is down
2. resizing the inner canvas while the mouse is dragging the right-bottom corner
3. check if auto-resizing while entering frame

The following are the code:

<mx:canvas id="outer"  enterFrame="handleEnterFrame(outer.mouseX, outer.mouseY)" mouseUp="handleMouseUp(inner.mouseX, inner.mouseY)" mouseDown="handleMouseDown(inner.mouseX, inner.mouseY)" mouseMove="handleMouseMove(inner.mouseX, inner.mouseY)" x="114" y="56" width="334" height="271" borderStyle="solid" borderColor="#FFFFFF" borderThickness="5">

<mx:canvas id="expander" x="0" y="0" width="{inner.width+ 20}" height="{inner.height + 20}">

<mx:canvas id="inner" x="10" y="10" width="200" height="200" borderStyle="solid" borderColor="#33444F" borderThickness="2">

</mx:canvas>

</mx:canvas>

</mx:canvas>


The above codes declare three canvases, outer, expander, and inner. The outer is the bound while holds the resizing canvas. The expander is one of the resized canvas who preserves 30 pixels offset between inner and outer.  The inner canvas is the one we want to resize.

private function handleMouseDown(x:Number, y:Number):void

{

if(x > (inner.width - 20) && y > (inner.height - 20))

{

m_MouseDown = true;

m_MouseOffsetX = x;

m_MouseOffsetY = y;

}

}


These codes handles mouse down event of  outer canvas, but the x and y arguments are mouseX and mouseY of inner canvas. This method marks mouse down while a user presses right-bottom corner.

private function handleMouseUp(x:Number, y:Number):void

{

m_MouseOffsetX = 0;

m_MouseOffsetY = 0;

m_MouseDown = false;

}


These codes handles mouse up event of outer canvas. It marks mouse not down.

private function handleEnterFrame(x:Number, y:Number):void

{

if(m_MouseDown){

if(x > outer.width - 30 && x <>

{

inner.width += 1;

m_MouseOffsetX = inner.mouseX;

outer.horizontalScrollPosition+=2;

trace("Frame Increase X");

}

if(y > outer.height - 30 && y <>

{

inner.height += 1;

m_MouseOffsetY = inner.mouseY;

outer.verticalScrollPosition+=2;

trace("Frame Increase Y");

}

}

}


These codes actually resizing inner canvas. While user presses the right-bottom corner of inner canvas and moves the mouse to the offset between inner canvas and outer canvas, it auto-resizes. This method increase width or height of inner canvas by one and change the scroll bar position to the end.

The following is the view of the above code:


















 

2008年8月4日 星期一

Rotation in Flex

Rotation is a easy task in Flex. But it's not easy while developing an integrated editing environment. Recently, I was starting to write an editor for photos. I never learned graphics techniques. So, I don't know the vector graphics.

At the first, I found an equation to calculate a rotated point, which is x = dx + x*cos(a) - y*sin(a) and y = dy + x*sin(a) + y*cos(a). That's great. I use it anywhere to calculate a non-rotated point to rotated point. When calculating a rotated point to non-rotated point, I was going to find an equation too, but nothing found. At that time, I felt some thing wrong. Why I could find an equation but not its reverse equation. So, I open my only one book about graphics, Filthy Rich Client. I found I was totally wrong.

Rotation is always done by matrix of affine transform. We can find the equation I found before is the result of applying a rotated and shifted matrix. So, it doesn't need to use math equation to calculate all the time. All you need is just call: transformPoint. If you want to reverse it, just call invese() and then you can have a reversed matrix. It's simple and easy. 

Transform non-rotated to rotated:

var oMx:Matrix = new Matrix();

oMx.rotate(radian);

oMx.translate(dx, dy);

return oMx.transformPoint(new Point(x, y));


The dx and dy is the about point. The x and y is the relative point to the about point. The result of this method is a absolute point.

Transform rotated to non-rotated:

var oMx:Matrix = new Matrix();

oMx.rotate(radian);

oMx.translate(dx, dy);

oMx.invert();

return oMx.transformPoint(new Point(x, y));


The dx and dy is the about point. The x and y is the absolute point. The result of this method is the relative point to the about point.

The following is a sample applying the above functions (two points in the rect are the rotating point.):









 

2008年7月31日 星期四

顫抖的 RectTracker

RectTracker 在一個編輯環境中是不可缺少的項目。最近,福克斯在 Flex 中企圖設計一個與 C#或 Java 一樣的 RectTracker。福克斯是採用 Mac OS X 的作業系統,就在開發的過程中,看似順利的程式,內部其實暗藏著一些問題。

就在福克斯設計好後,沒想到悲慘的事情發生了。居然福克斯寫的 RectTracker 在放大的過程中,會出現顫抖的狀態。這個情況在 C# 或是 Java 從來沒發生過。

2008年7月30日 星期三

開台心得

福克斯在學習 Flex 之前,其實是一個 Java, C#, Javascript, C++ ... 等的軟體工程師。為什麼福克斯會想要學習 Flex。最主要的原因是,福克斯相信,未來的系統必定是具備『動感』的這個項目。到底,什麼是『動感』呢?大家可以看一下許多的 Flash 網站,及 Apple 推出的產品,例如 Mac OSX, iPhone...等。

說真的,福克斯在學習 Flex 的過程中,明顯有許多不適應的地方。雖然,福克斯學過各種不同的程式語言,但是像 Flex 這種:1. 有點像 OO ,又有點不像 OO;2. 有點像 Strong typed,又有點像 Weak typed,的語言很少見。

所以,希望這個 Blog 能帶給大家一些幫助。