我有一个16x16网格的按钮,并希望为每个按钮添加一个事件监听器,因此当点击它时,它将返回其唯一的网格位置编号(0-255之间的任何内容); 到目前为止我所拥有的:
public static const GRID_SIZE:Number = 16;
private var i:int;
private var j:int;
// Constructor
public function Grid()
{
for (i = 0; i < GRID_SIZE; i++)
{
for (j = 0; j < GRID_SIZE; j++)
{
// Creates new instance of GridButton, a custom class that extends SimpleButton
var button:GridButton = new GridButton();
// Arranges buttons into a grid
button.x = (i + 1) * button.width;
button.y = (j + 1) * button.height;
// Create unique value for grid position
var position:Number = i * GRID_SIZE + j;
// Add listener to button, with position as extra param
button.addEventListener(MouseEvent.CLICK, function(e:MouseEvent) : void { buttonClick(e, position) } );
// Adds button to Sprite
addChild(button);
}
}
}
}
不幸的是,每次按钮调用侦听器函数时,它都使用i和j的最后两个值,在这种情况下,每个按钮返回255.
有什么建议吗?
答案 0 :(得分:1)
您可以为此按钮添加名称,例如button.name = "button" + position;
,在事件处理函数中,您可以从目标名称(e.target.name
)中提取位置参数:
button.name = "button" + position;
button.addEventListener(MouseEvent.CLICK, buttonClick);
和事件处理程序:
function buttonClick(e:MouseEvent) {
var position:Number = Number(e.target.name.replace("button", ""));
// ... do wathever you want with position parameter
}
答案 1 :(得分:1)
还有其他一些选择......
1 使用signals代替flash事件侦听器,here's a post描述它并提供更多详细信息。还有一个video tutorial可以帮助您快速入门。我建议这样做的原因是你可以设置一个信号来传递参数,所以你不需要使用事件目标,这并不总是最好的。
2 使用功能工厂。
// factory:
public function fooFactory($mc:GridButton):Function{
var $f:Function = new Function($e:MouseEvent):void{
trace($mc.x, $mc.y);
}
// you might want to consider adding these to a dictionary or array, so can remove the listeners to allow garbage collection
return $f;
}
// then assign the function to the button like this
button.addEventListener(MouseEvent.CLICK, fooFactory(button) );
这基本上是你想要做的,但它会起作用,因为position
var没有改变。在你的代码中,position
每次循环执行时都会发生变化,然后当你触发监听器函数时,它会使用position
分配的最后一个值,这就是为什么你为所有这些值得到255的原因。如果这没有意义,请告诉我......
答案 2 :(得分:1)
通过在匿名函数中使用外部作用域中的变量,你已经遇到了关闭和内存泄漏的大问题:position
中使用了function(e:MouseEvent)
,但它是在function Grid()
中创建的,所以它会遵守function Grid()
的变化。而且你正在处理你添加的256 function(e:MouseEvent)
个但不能删除的内存!
让我们用最简单的工作方式重新编写代码:
public static const GRID_SIZE:Number = 16;
private var i:int;
private var j:int;
public function Grid() {
var functions:Object;
for (i = 0; i < GRID_SIZE; i++) {
for (j = 0; j < GRID_SIZE; j++) {
var button:GridButton = new GridButton();
button.x = (i + 1) * button.width;
button.y = (j + 1) * button.height;
var position:Number = i * GRID_SIZE + j;
functions[position] = buttonClick(position);
button.addEventListener(MouseEvent.CLICK, functions[position]);
//button.removeEventListener(MouseEvent.CLICK, functions[position]);
addChild(button);
}
}
buttonClick(position:Number):Function {
return function(e:MouseEvent):void {
// Now you can use both unique "e" and "position" here for each button
}
}
}
由于您要添加256个侦听器,因此必须将每个侦听器存储在不同的变量中(属性列表functions[position]
),因此您可以安全地删除每个以释放内存< / strong>与添加它们的方式相同。
这是从this answer详细阐述的。
答案 3 :(得分:0)
您可以从用于将x和y值分配给按钮的相同表达式中取回i和j的值。例如:
button.addEventListener(MouseEvent.CLICK, clickHandler);
function clickHandler(e:MouseEvent) {
var i:int = (e.target.x / e.target.width) - 1;
var j:int = (e.target.y / e.target.height) - 1;
var position:Number = i * GRID_SIZE + j;
}
答案 4 :(得分:0)
我试过这个并且它运行良好....单击不同的文本字段可以追踪不同的值。 我的想法是创建一个对pos:Number的新引用,这样即使在更新pos之后,闭包仍然指向旧的
package
{
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.text.TextField;
import flash.text.TextFieldType;
public class AsDing extends Sprite
{
private static const GRID_SIZE:uint = 2;
public function AsDing()
{
for(var i:uint=0; i<GRID_SIZE; i++)
{
for(var j:uint=0; j<GRID_SIZE; j++)
{
var tf:TextField = new TextField();
var pos:Number = i*GRID_SIZE + j;
tf.text = pos.toString();
tf.type = TextFieldType.DYNAMIC;
tf.addEventListener(MouseEvent.MOUSE_DOWN, createMCHdlr(pos));
addChild(tf);
tf.x = i*100; tf.y = j*100;
}
}
}
private function createMCHdlr(pos:Number):Function
{
var ret:Function = function(evt:MouseEvent):void
{
trace('pos: ' + pos);
};
return ret;
}
}
}