1
votes

This seems simple in other languages, but I don't understand the error. I have 7 buttons that I would like to each take my gallery movieclip to a certain frame when you click on them.

Error: 1067: Implicit coercion of a value of type int to an unrelated type flash.events:MouseEvent.
Error: 1136: Incorrect number of arguments.  Expected 2.
Error: 1067: Implicit coercion of a value of type void to an unrelated type Function.

Any help?

function gotoImage(event:MouseEvent, frameParam:int):void
{
MovieClip(this.root).gallery.gotoAndStop(frameParam);
}


t1.addEventListener(MouseEvent.CLICK, gotoImage(1));
t2.addEventListener(MouseEvent.CLICK, gotoImage(2));
t3.addEventListener(MouseEvent.CLICK, gotoImage(3));
t4.addEventListener(MouseEvent.CLICK, gotoImage(4));
t5.addEventListener(MouseEvent.CLICK, gotoImage(5));
t6.addEventListener(MouseEvent.CLICK, gotoImage(6));
t7.addEventListener(MouseEvent.CLICK, gotoImage(7));
3

3 Answers

2
votes

Just change this

t1.addEventListener(MouseEvent.CLICK, function(me:MouseEvent):void{ gotoImage(me, 1)});
t2.addEventListener(MouseEvent.CLICK, function(me:MouseEvent):void{ gotoImage(me, 2)});

and so on...

3
votes

You've got two things off with your code:

  1. First, in ActionScript, event handlers always have the same signature:

    function someHandler(e:Event):void { .. }
    

    Sometimes the Event argument is a more specific subclass of Event, such as MouseEvent, but there is always just one argument.

  2. The addEventListener method needs a function itself, not the result of invoking a function.

    // Here's a function:
    function multiply(i1:int, i2:int):int { return i1 * i2; }
    
    // Here's assigning the result of **invoking** a function:
    var result:int = multiply(2,3); 
    
    // Here's assigning a **function itself** to a variable:
    var f:Function = multiply;
    
    // You can invoke the function via the variable f in two different ways:
    var result1 = f(2,3);
    var result2 = f.apply(null, [2,3]);
    

So, you'll need to change your code to follow the above to points. You'll have to associate the buttons with jumping to a specific frame one of two ways:

  1. Simple but repetitive: Use a separate handler for each button, with the frame hard coded into each handler.

    1a. Named functions (most verbose):

    function onT1Click(e:MouseEvent):void {               
        MovieClip(this.root).gallery.gotoAndStop(1);
    }
    
    t1.addEventListener(MouseEvent.CLICK, onT1Click);
    // etc. etc.
    

    1b. Anonymous functions:

    t1.addEventListener(MouseEvent.CLICK, function(e:Event):void { 
        MovieClip(this.root).gallery.gotoAndStop(1);
    });
    // etc. etc.
    
  2. More elegant: Use the same handler, and store the association between button and frame elsewhere, such as in a Dictionary. If you stick with your naming convention you could even fill the Dictionary in a for loop getting the buttons by name:

    var buttonToFrame:Dictionary = new Dictionary();
    for(var i:int = 1; i < 8; i++) {
        var btn:Button = this["t" + i.toString()];
        buttonToFrame[btn] = i;
        btn.addEventListener(MouseEvent.CLICK, onClick);
    }
    
    function onClick(e:MouseEvent):void {
        var btn:Button = Button(e.currentTarget);
        var frameNum:int = buttonToFrame[btn];
        MovieClip(this.root).gallery.gotoAndStop(frameNum);
    }
    
0
votes

This is possible with a roundabout approach. For the event handler, use a function that returns a nested anonymous function.

private var textFieldA:TextField = new TextField;
private var textFieldB:TextField = new TextField;

public function setParameterizedTextWhenTextFieldsAreClicked ():void {
    addChild(textFieldA);
    textFieldA.text = 'Text field A';
    textFieldA.addEventListener(MouseEvent.CLICK, showCustomMessage("One"));

    addChild(textFieldB);
    textFieldB.text = 'Text field B';
    textFieldB.y = 20;
    textFieldB.addEventListener(MouseEvent.CLICK, showCustomMessage("Two"));
    // NOTE: We must use strongly referenced listeners because weakly referenced 
    // listeners **will get garbage collected** because we're returning
    // an anonymous function, which gets defined in the global namespace and  
    // thus, the garbage collector does not have anything pointing to it.
}

private function showCustomMessage (message:String):Function {
    // NOTE: You can store the following function to a class variable
    // to keep it in memory, which would let you use weakly referenced 
    // listeners when using this as an event handler. Many people 
    // would find that awkward. I would discourage that.
    return function (e:MouseEvent):void {
        var textField:TextField = e.target as TextField;
        textField.text = message; // "message" argument is available because 
                                  // this function's scope is kept in memory.
    }
}

Bear in mind, the use of anonymous functions and reliance on function scope being kept in memory seem to present garbage collection complications.