Flex的AS3:进度条不动 [英] Flex AS3: ProgressBar doesn't move

查看:136
本文介绍了Flex的AS3:进度条不动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有点卡住,需要一些意见/帮助。

我有一个进度条:

 < MX:进度条的id =appProgress模式=手动WIDTH =300的标签={appProgressMsg}最低=0最大=100/ >
 

我有两个监听功能,一是设置进度,和一个设置appProgressMsg:

 公共职能incProgress(E:TEvent):无效{
    VAR号码:UINT = Math.floor(e.data.number / e.data.total * 100);
    跟踪(设置打击乐。+ P);
    appProgress.setProgress(对,100);
}
公共职能setApplicationProgressStep(E:TEvent):无效{
    跟踪(设置步骤:+ e.data);
    appProgressMsg = e.data;
}
 

我想重新使用这个进度条了很多。并且不一定用于ProgressEvents,但经历步骤时

例如,我遍历了一堆数据库插入的,并希望undate进度等。

下面是一个例子:

 公共职能updateDatabase(结果:对象):无效{
    VAR总:= 0;
    变种我:= 0;
    变种R:的SQLResult;
    跟踪(updateDatabase叫。);
    每个(VAR表:XML在this.queries.elements(表)){
        VAR键:字符串= table.attribute的(名称);
        如果(结果[关键]){
            发送(TEvent.UpdateApplicationProgressStep,更新+键);
            I = 1;
            总=结果[关键] .length;
            每个(VAR行:在结果对象[关键]){
                //现在,我们必须看到,如果我们已经有这条记录。
                发送(TEvent.UpdateApplicationProgress,{:我总:总});
                R = this.query(SELECT * FROM+按键+,其中SERVER_ID ='+ row.id +');
                如果(r.data == NULL){
                    //存在与此ID的条目,做一个。
                    this.query(table.insert,行);
                } 其他 {
                    //它的存在,让我们更新。
                    this.update(键,行);
                }
                我++;
            }
        }

    }
}
 

一切工作正常。

也就是说,监听器函数的调用,我得到这样的跟踪输出:

  updateDatabase调用。
设置步骤:更新项目
设置四氯乙烯25
设置四氯乙烯50
设置四氯乙烯75
设置四氯乙烯100
 

问题是,只有最后%,而步骤示。也就是说,当这一切都完成,进度条跳跃到100%,显示了在最后一步标签

有谁知道这是为什么?

在此先感谢您的帮助, 杰森

新的code,其中工程赫然我想补充:

 公共职能updateDatabase(结果:对象,eindex:= 0,SINDEX:= 0):无效{
    VAR总:= 0;
    变种我:= 0;
    VAR记者:INT;
    变种R:的SQLResult;
    无功表:XML;
    VAR键:字符串;
    VAR elems:返回XMLList = this.queries.elements(表);
    VAR的startTime:INT =的getTimer();
    VAR行:对象;
    对于(i = eindex; I< elems.length();我++){
        表= elems [I]
        键= table.attribute的(名称);
        如果(!结果[关键])
            继续;
        总=结果[关键] .length;
        发送(TEvent.UpdateApplicationProgressStep,更新+键);
        为(J = SINDEX; J<导致[关键] .length; J ++){
            如果(的getTimer() - 的startTime→100){
                的setTimeout(updateDatabase,100,结果,I,J);
                发送(TEvent.UpdateApplicationProgress,{号:J-,总:总});
                返回;
            }
            行=结果[关键] [J]。
            R = this.query(SELECT * FROM+按键+,其中SERVER_ID ='+ row.id +');
            如果(r.data == NULL){
                //存在与此ID的条目,做一个。
                this.query(table.insert,行,假);
            } 其他 {
                //它的存在,让我们更新。
                this.update(关键字,行,假);
            }
        }
        发送(TEvent.UpdateApplicationProgress,{数:1,总:1});
    }
}
 

解决方案

Flash是单线程的。显示屏将不会更新,直到你的函数返回。出于这个原因,你永远不应该有运行比约100毫秒(一秒的1/10日)不再会出现被锁定任何code,否则用户界面(甚至整个浏览器)。

一般的解决方法就是分裂您的工作在多个帧,这里是一些伪code:

 函数的doWork(ARG1:OBJ,ARG2:OBJ,开始:= 0){
   VAR的startTime =的getTimer(); //存储开始时间
   对于(i =启动; I<长度;我++){
     如果(的getTimer() -  startTime时→100){//看看我们是否已经工作太久
        跟踪(当前进度:+(I /长* 100)+%);
        的UpdateProgress(ⅰ/长度);
        的setTimeout(的doWork,100,ARG1,ARG2,我); //时间表更多的工作要做
        返回; //停止电流回路
     }
     跟踪(工作的项目+ I);
     这里//处理
   }
   跟踪(所有的工作做得);
}

的doWork(数据1,数据2); //启动工作
 

I am a little stuck and need some advice/help.

I have a progress bar:

<mx:ProgressBar id="appProgress" mode="manual" width="300" label="{appProgressMsg}" minimum="0" maximum="100"/>

I have two listener functions, one sets the progress, and one sets the appProgressMsg:

public function incProgress(e:TEvent):void {
    var p:uint = Math.floor(e.data.number / e.data.total * 100);
    trace("Setting Perc." + p);
    appProgress.setProgress(p, 100);
}
public function setApplicationProgressStep(e:TEvent):void {
    trace("Setting step:" + e.data);
    appProgressMsg = e.data;
}

I want to reuse this progress bar alot. And not necessarily for ProgressEvents, but when going through steps.

For instance, I loop over a bunch of database inserts, and want to undate the progress etc.

Here is a sample:

public function updateDatabase(result:Object):void {
    var total:int = 0;
    var i:int = 0;
    var r:SQLResult;
    trace("updateDatabase called.");
    for each (var table:XML in this.queries.elements("table")) {
        var key:String = table.attribute("name");
        if (result[key]) {
            send(TEvent.UpdateApplicationProgressStep, "Updating " + key);
            i = 1;
            total = result[key].length;
            for each (var row:Object in result[key]) {
                //now, we need to see if we already have this record.
                send(TEvent.UpdateApplicationProgress, { number:i, total: total } );
                r = this.query("select * from " + key + " where server_id = '" + row.id + "'");
                if (r.data == null) {
                    //there is no entry with this id, make one.
                    this.query(table.insert, row);
                } else {
                    //it exists, so let's update.
                    this.update(key, row);
                }
                i++;
            }
        }

    }
}

Everything works fine.

That is, the listener functions are called and I get trace output like:

updateDatabase called.
Setting step:Updating project
Setting Perc 25
Setting Perc 50
Setting Perc 75
Setting Perc 100

The issue is, only the very last percent and step is shown. that is, when it's all done, the progress bar jumps to 100% and shows the last step label.

Does anyone know why this is?

Thanks in advance for any help, Jason

The new code, which works awesomely I might add:

public function updateDatabase(result:Object, eindex:int = 0, sindex:int = 0 ):void {
    var total:int = 0;
    var i:int = 0;
    var j:int;
    var r:SQLResult;
    var table:XML;
    var key:String;
    var elems:XMLList = this.queries.elements("table");
    var startTime:int = getTimer();
    var row:Object;
    for (i = eindex; i < elems.length(); i++) {
        table = elems[i];
        key = table.attribute("name");
        if (!result[key])
            continue;
        total = result[key].length;
        send(TEvent.UpdateApplicationProgressStep, "Updating " + key);
        for (j = sindex; j < result[key].length; j++) {
            if (getTimer() - startTime > 100) {
                setTimeout(updateDatabase, 100, result, i, j);
                send(TEvent.UpdateApplicationProgress, { number:j, total: total } );
                return;
            }
            row = result[key][j];
            r = this.query("select * from " + key + " where server_id = '" + row.id + "'");
            if (r.data == null) {
                //there is no entry with this id, make one.
                this.query(table.insert, row,false);
            } else {
                //it exists, so let's update.
                this.update(key, row,false);
            }
        }
        send(TEvent.UpdateApplicationProgress, { number:1, total: 1 } );
    }
}

解决方案

Flash is single threaded. The display will not update until your function returns. For this reason, you should never have any code that runs for longer than about 100ms (1/10th of a second), otherwise the UI (or even the entire browser) will appear to be locked up.

The general solution is to split up your work over multiple frames, here is some pseudo-code:

function doWork(arg1:Obj, arg2:Obj, start:int=0) {
   var startTime = getTimer(); // store starting time
   for(i=start; i<length; i++) {
     if(getTimer() - startTime > 100) { // see if we've been working too long
        trace("Current progress: "+(i/length * 100)+"%");
        updateProgress( i / length );
        setTimeout(doWork, 100, arg1, arg2, i); // schedule more work to be done
        return; // stop current loop
     }
     trace("Working on item "+i);
     // processing here
   }
   trace("All work done");
}

doWork(data1, data2); // start the work

这篇关于Flex的AS3:进度条不动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆