我正在制作一个简单的工具,让用户最终将图像保存到磁盘。
为此,我使用FileStream
类及其writeBytes()
方法。
这很有效。当我尝试使用简单的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 :(得分:3)
文件保存多大?
在保存文件方面,您的代码似乎很好。但是,我怀疑实际上花了很长时间才将文件编码为PNG格式。不幸的是,PNGEncoder
不会发送任何进度事件。但是你应该查看这个project from Lee Burrows,或者考虑使用Actionscript Workers在另一个线程中进行编码。
快速证明它的方法:在编码为PNG之前/之后添加跟踪语句。大延迟是对应于此阶段还是实际保存?
如果这没有帮助,请指定文件的大小,以及是否收到0,1或多个OUTPUT_PROGRESS事件。
答案 1 :(得分: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());
您可以跟踪写入文件的进度(虽然我怀疑这并不需要太多时间,如Sunil所说),如下所示:
bytes.position = 0;
while(bytes.bytesAvailable > 0) {
fileStream.writeByte(bytes.readByte());
trace("progress:", bytes.position / bytes.length * 100); // multiply by 100 for percentage
}
请注意,此方法需要一名工作人员,否则进度只会在保存完成后直观更新。
答案 2 :(得分:1)
Sunil是对的。写文件几乎不需要花点时间。它解码阻塞应用程序的字节数组。我实现了以下代码来测试它。
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();
}
}
您需要在解码任务上使用进度指示器而不是文件写入任务。工作者似乎是最好的解决方案,但这取决于您需要针对哪个版本的运行时。