2013-07-04 63 views
1

我正在製作一個簡單的工具,讓用戶最終將圖像保存到磁盤。 爲了做到這一點,我使用FileStream類和它的writeBytes()方法。如何在Flex中顯示FileStream的保存進度?

這工作很好。當我試圖用簡單的mx:ProgressBar來顯示保存進度時,問題就發生了。我嘗試了一些方法,但似乎沒有任何工作。

這裏是ActionScript代碼片段:

private function save(file:File, image:MyImageClass):void { 
    var data:BitmapData = new BitmapData(width, height, true, 0x000000); 
    image.draw(data, _cols); 
    var bytes:ByteArray = new PNGEncoder().encode(data); 
    fileStream = new FileStream(); 
    fileStream.addEventListener(OutputProgressEvent.OUTPUT_PROGRESS, onProgress); 
    fileStream.addEventListener(Event.CLOSE, onClose); 
    try { 
     fileStream.openAsync(file, FileMode.WRITE); 
     fileStream.writeBytes(bytes); 
    } catch (e:Error) { 
     Alert.show("Error trying to save the image: " + e.message); 
    } finally { 
     fileStream.close(); 
    } 
} 

private function onProgress(event:OutputProgressEvent):void { 
    var progressRatio:Number = (1 - (event.bytesPending/event.bytesTotal)); 
    progressBar.setProgress(progressRatio, 1); 
    trace(progressRatio); 
    if (event.bytesPending == 0) 
     event.target.close(); 
} 

private function onClose(event:Event):void { 
    trace("closed"); 
} 

和進度條的MXML:

<mx:ProgressBar id="progressBar" mode="manual"/> 

執行此我有一個冷凍接口時,該文件被完全保存被釋放並在控制檯上同時獲取所有的痕跡。進度條保持在0%,直到界面被解凍並達到100%。

我知道Flash是單線程的,但我認爲FileStream.openAsync()方法應該做骯髒的工作,使我的接口負責。做這個簡單和(我認爲)通用的任務不應該很難。

問題是:我做錯了什麼?

在此先感謝

+0

只是一個更正; Flash Player不是單線程的。雖然他們不給程序員控制自己線程的能力。 「工作人員」功能將在即將發佈的版本中爲程序員提供「線程化」功能。但是,僅僅因爲我們無法產生我們自己的線程(但)並不意味着該程序是單線程的。 – JeffryHouser

+1

@Reboog711 Actionscipt工作人員實際上早已被釋放。 – Gio

+0

@Gio我應該在發帖之前查看它。我不確定他們是否「最近」,或者我們是否仍在等待。他們去年十月被加入Flash Player 11.4。 – JeffryHouser

回答

3

保存的文件有多大?

您的代碼似乎很好,就保存文件而言。但是,我懷疑實際上需要很長時間才能將文件編碼爲PNG格式。不幸的是,PNGEncoder不派遣任何進度事件。但是你應該看看這個project from Lee Burrows,或者考慮使用Actionscript Workers在不同的線程中進行編碼。

快速的方法來證明它:在編碼到PNG之前/之後添加跟蹤語句。大延遲是否與這個階段相符,還是與實際保存相對應?

如果這沒有幫助,請指定您的文件的大小以及是否獲得0,1或多個OUTPUT_PROGRESS事件。

1

我同意Sunil,但我想添加一兩件事。

首先,我建議使用BitmapData類的新方法編碼圖像,因爲它更快更容易。所以,你的代碼將改變這樣的事情:

var data:BitmapData = new BitmapData(width, height, true, 0x000000); 
image.draw(data, _cols); 
var bytes:ByteArray = data.encode(data.rect, new PNGEncoderOptions()); 

您可以跟蹤寫入文件的進展(雖然我懷疑這是不是需要很長時間,像蘇尼爾說的)這樣的:

bytes.position = 0; 
while(bytes.bytesAvailable > 0) { 
    fileStream.writeByte(bytes.readByte()); 
    trace("progress:", bytes.position/bytes.length * 100); // multiply by 100 for percentage 
} 

請注意,您需要一名工作人員使用此方法,否則只有在保存完成後纔會以可視方式更新進度。

1

蘇尼爾是正確的。寫入文件幾乎不需要一點時間。它解碼阻止應用程序的字節數組。我實現了下面的代碼來測試它。

private function save(file:File):void 
{ 
    var bytes:ByteArray = new ByteArray(); 
    //233348 - very fast (requires 6000 x 10000 bitmap pixels) 
    //252790 - very fast (requires 6500 x 10000 bitmap pixels) 
    //2488990 - need a whole magnitude more of data in order to show the progress messages 
    for (var i:int = 0; i < 2488990; i++) 
    { 
     bytes.writeByte(1); 
    } 
    var fileStream:FileStream = new FileStream(); 
    fileStream.addEventListener(OutputProgressEvent.OUTPUT_PROGRESS, onProgress); 
    fileStream.addEventListener(Event.CLOSE, onClose); 
    try { 
     fileStream.openAsync(file, FileMode.WRITE); 
     fileStream.writeBytes(bytes); 
    } catch (e:Error) { 
     //Alert.show("Error trying to save the image: " + e.message); 
    } finally { 
     fileStream.close(); 
    } 
} 

您將需要一個關於解碼任務而不是文件寫入任務的進度指示器。工人似乎是最好的解決方案,但這取決於您需要針對哪個版本的運行時。

相關問題