AS3 - 更新数组后自动刷新显示

AS3 - Auto refreshing display after updating array

所以,基本上我是在重新发明轮子,尝试在 Flash 中制作一种电子表格来跟踪游戏中的会员增长情况。在这一节中,我将成员名称添加到一个数组中,然后将名称放入动态创建的图块中,并附加文本字段以显示名称。

我有一个保存数组的保存按钮,如果我保存、关闭并重新打开,那么我可以看到我添加的成员。但是,我希望它在数组更改后立即刷新舞台以反映所做的更改(更新电子表格)。我还将动态地添加和删除其他图块,但我可以将此问题的解决方案外推到所有这些之后。

这是我必须添加成员并创建显示的代码:

public var mainArray:Array = new Array;
public var i1:Number = 0;
public var memberBox:MovieClip = new MovieClip();
public var MAX_ROWS = 0;
public var MAX_COLS = 0;

public function Tracker() {
    MAX_COLS = mainArray.length - 1;
    addBtn.addEventListener(MouseEvent.CLICK, addFun); //atchaed to button on stage
    public function addFun($e:MouseEvent):void{
        mainArray[i1] = [];
        mainArray[i1][0] = addNameTxt.text //attached to textfield on stage
        i1++;
        loadMembers();

    public function loadMembers():void{

        var multiDimensionalArray:Array = new Array();


        //initalize the arrays
        for (var row = 0; row <= MAX_ROWS; row++)
        {
            var boolArray:Array = new Array();

            for (var col = 0; col <= MAX_COLS; col++){
                boolArray.push(false);
            }

            multiDimensionalArray.push(boolArray);
        }

        //now we can set the values of the array as usual
        for (var row = 0; row <= MAX_ROWS; row++)
        {
            for (var col = 0; col <= MAX_COLS; col++){

                multiDimensionalArray.push(1); ;
            }
        }
        //create a column of tiles based on mainArray length with a textfield attached to each
        buildLevel(multiDimensionalArray);

    }

        public function buildLevel(s:Array){
            var txtArray:Array = new Array();
            memberBox.name = "tileHolder";
            for(var i=0; i  < MAX_ROWS + 1; i++){
                for(var o=0; o < MAX_COLS + 1; o++){
                    var currentTile:MemberBox = new MemberBox();
                    currentTile.x = i*150;
                    currentTile.y = o*25;
                    currentTile.name = "b"+o;
                    memberBox.addChild(currentTile);
                    //currentTile.gotoAndStop(int(s[o][i]));
                    var memberTxt:TextField=new TextField(); 
                    currentTile.addChild(memberTxt);
                    memberTxt.width = 150;
                    memberTxt.height = 25;
                    txtArray[o] = memberTxt;
                    txtArray[o].text = mainArray[o][0];

                    }

                }

                memberBox.x = 60;
                memberBox.y = 170;
                addChild(memberBox);

            }


}

理想的解决方案是将事件侦听器附加到数组,但是,数组不会触发事件。

解决方案 #1:托管更新

与其让任何代码直接修改您的数组,不如编写一个函数来处理更新您的数组。这样,您可以同时知道什么时候更新显示。

public var mainArray:Array = new Array;
public var i1:Number = 0;
public var memberBox:MovieClip = new MovieClip();
public var MAX_ROWS = 0;
public var MAX_COLS = 0;

public function Tracker() {
    MAX_COLS = mainArray.length - 1;
    addBtn.addEventListener(MouseEvent.CLICK, addFun); //attached to button on stage

    public function addFun(e:MouseEvent):void {
        mainArray[i1] = [];
        mainArray[i1][0] = addNameTxt.text //attached to textfield on stage
        i1++;
        loadMembers();
    }

    public function loadMembers():void {
        var multiDimensionalArray:Array = new Array();

        //initalize the arrays
        for (var row = 0; row <= MAX_ROWS; row++) {
            var boolArray:Array = new Array();

            for (var col = 0; col <= MAX_COLS; col++) {
                boolArray.push(false);
            }

            multiDimensionalArray.push(boolArray);
        }

        //now we can set the values of the array as usual
        for (var row = 0; row <= MAX_ROWS; row++) {
            for (var col = 0; col <= MAX_COLS; col++) {
                multiDimensionalArray.push(1); ;
            }
        }
        //create a column of tiles based on mainArray length with a textfield attached to each
        buildLevel(multiDimensionalArray);

    }

    public function buildLevel(s:Array) {
        var txtArray:Array = new Array();
        memberBox.name = "tileHolder";
        for (var i:int = 0; i < MAX_ROWS + 1; i++) {
            for(var o=0; o < MAX_COLS + 1; o++) {
                var currentTile:MemberBox = new MemberBox();
                currentTile.name = i + "_" + o;
                currentTile.x = i*150;
                currentTile.y = o*25;
                memberBox.addChild(currentTile);
                //currentTile.gotoAndStop(int(s[o][i]));
                var memberTxt:TextField=new TextField(); 
                currentTile.addChild(memberTxt);
                memberTxt.width = 150;
                memberTxt.height = 25;
                txtArray[o] = memberTxt;
                txtArray[o].text = mainArray[o][0];
            }
        }

        memberBox.x = 60;
        memberBox.y = 170;
        addChild(memberBox);
    }

    public function modifyArray(row:int, col:int, value:*):void {
        // Update our array.
        mainArray[row][col] = value;

        // Update our tile.
        var tile:MemberBox = memberBox.getChildByName(row + "_" + col);
        tile.getChildAt(0).text = value;
    }
}

当你实际修改你的数组时,你会用你的函数来做,而不是直接的 mainArray[o][i] 方法。

// Instead of this
mainArray[o][i] = "foo";

// You'd do this
modifyArray(o, i, "foo");

更新: 我不确定如何更好地解释这一点,所以我发布了您可以查看的工作示例。它包含 class、文档代码、fla 和 swf,以及电子表格的工作更新。让我知道这是否解决了问题:SpreadSheet Test @ Dropbox

解决方案 #2:轮询更改

在内存中保存数组的两​​个版本。第一个是您正在编辑的,第二个是未修改的副本,用于与第一个进行比较。您每隔一段时间(每秒一次?)迭代整个数据集并寻找差异。找到一个后,更新重复数组和显示的电子表格。

下面是您如何执行此操作的示例:

import flash.utils.*;

var last:Number = flash.utils.getTimer();
this.addEventListener("enterFrame", checkData);

var foo:Array = ["a", "b", "c"];
var fooBackup:Array = [];

function update():void {
    var txt:TextField;

    for (var i:int = 0; i < foo.length; i++) {
        // If we don't have a representation of this index, create one.
        if (!this.getChildByName("tile"+i)) {
            txt = new TextField();
            txt.name = "tile" + i;
            txt.text = foo[i];
            this[txt.name] = txt;
            addChild(txt);
            txt.y = i * 20;
        }

        // Update the data if inconsistent.
        txt = this.getChildByName("tile"+i) as TextField;
        if (fooBackup.hasOwnProperty(i) == false || foo[i] != fooBackup[i]) {
            fooBackup[i] = foo[i]
            txt.text = foo[i];
            trace("Index " + i + " changed.  Updated backup, and display.");
        }
    }
}

function checkData(e:Event):void {
    var now:Number = flash.utils.getTimer();

    // If the last time we checked is greater than a second, run the check again.
    if (now - last > 1000) {
        // Update last checked index;
        last += 1000;

        // For the sake of argument, let's randomly change an index to a random value.
        foo[random(0, foo.length-1)] = random(-1000, 1000);
        update();
    }
}

 function random(low:Number=0, high:Number=1):Number {
    /* Returns a random number between the low and high values given. */
    return Math.floor(Math.random() * (1+high-low)) + low;
}

解决方案 #3:滚动你自己的数组

正如 Adob​​e 的 Extending the Array class 所述,您可以子 class 数组并在您 add/remove 条目时从那里添加您自己的事件调度。这是更冒险的解决方案,并且(以我的拙见)是最好的解决方案,因为它保持了代码的一致性,同时提供了广泛而有效的权力。