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:滚动你自己的数组
正如 Adobe 的 Extending the Array class 所述,您可以子 class 数组并在您 add/remove 条目时从那里添加您自己的事件调度。这是更冒险的解决方案,并且(以我的拙见)是最好的解决方案,因为它保持了代码的一致性,同时提供了广泛而有效的权力。
所以,基本上我是在重新发明轮子,尝试在 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:滚动你自己的数组
正如 Adobe 的 Extending the Array class 所述,您可以子 class 数组并在您 add/remove 条目时从那里添加您自己的事件调度。这是更冒险的解决方案,并且(以我的拙见)是最好的解决方案,因为它保持了代码的一致性,同时提供了广泛而有效的权力。