|
-
[RESOLVED] How to add key listener to the stage
I want to add a key listener to my stage, but from an object 2 depths below the stage. How would I do this?
I thought about adding the listener from my doc class, but the listener function is in the object that is two depths below the stage, which would mean I would have to pass the key values to the next movie clip, then when that one is loaded, pass it to the one with the listener function. It seems very complicated, is there an easier way which keeps with the principle of OOP?
-
A keyboard event listener is one of the few times that it is acceptable to add a listener to the stage.
Code:
stage.addEventListener(KeyboardEvent.KEY_DOWN, someFunction);
as long as the clip is on the display list already, that'll work.
I don't understand your objection about the doc class. What do you mean you'd have to pass key values around?
-
 Originally Posted by 5TonsOfFlax
A keyboard event listener is one of the few times that it is acceptable to add a listener to the stage.
Code:
stage.addEventListener(KeyboardEvent.KEY_DOWN, someFunction);
as long as the clip is on the display list already, that'll work.
I don't understand your objection about the doc class. What do you mean you'd have to pass key values around?
See my clip is on the display list but when I add my listeners to it, I get the following error: TypeError: Error #1009: Cannot access a property or method of a null object reference. When I tarce this.stage from inside the clip, I get null.
-
Then it's not on the display list. Why do you think it is?
Is it maybe on a different frame? Stuff on a different frame isn't yet on the display list.
-
 Originally Posted by 5TonsOfFlax
Then it's not on the display list. Why do you think it is?
Is it maybe on a different frame? Stuff on a different frame isn't yet on the display list.
No it should be on the display list. I traced this.parent and it displays it's parent. Also, the object is added to the stage when I export the swf, its just functionally it doesn't work.
-
If that object's stage property is null, it is not on the display list. Period.
It can have a non-null parent property. That parent may not be on the display list.
The quickest fix is to add the key listener within a listener for ADDED_TO_STAGE, but that won't tell you what is really going wrong with the way you currently have it.
Code:
addEventListener(Event.ADDED_TO_STAGE, stageInit);
function stageInit(e:Event):void{
stage.addEventListener(KeyboardEvent.KEY_DOWN, someFunction);
}
-
A keyboard event listener is one of the few times that it is acceptable to add a listener to the stage.
Out of curiosity, can you elaborate on this? Personally I use stage listeners frequently for singleton type interactivity (i.e tooltips, text input) or for communication between separate branches of the display list.
-
 Originally Posted by 5TonsOfFlax
If that object's stage property is null, it is not on the display list. Period.
It can have a non-null parent property. That parent may not be on the display list.
The quickest fix is to add the key listener within a listener for ADDED_TO_STAGE, but that won't tell you what is really going wrong with the way you currently have it.
Code:
addEventListener(Event.ADDED_TO_STAGE, stageInit);
function stageInit(e:Event):void{
stage.addEventListener(KeyboardEvent.KEY_DOWN, someFunction);
}
Thanks for your help. I'll use that ADDED to stage listener to check whats going on.
-
Can you see if there is something wrong with this snippet of code, because I am doing as you say, only adding keylisteners when item added to stage but I am still getting that null error:
addEventListener(Event.ADDED_TO_STAGE, stageInit);
}
function stageInit(e:Event):void{
trace(e.target)
addEvent()
}
function addEvent(){
this.focusRect=false;
stage.focus=this;
this.stage.addEventListener(KeyboardEvent.KEY_DOWN ,keyUpHandler);
this.stage.addEventListener(KeyboardEvent.KEY_UP,k eyDownHandler);
}
-
I should have added a "In my opinion" to precede that.
I don't like to mess with the stage. It's a common resource for all swfs running in that vm. It just seems like a return to the old as2 _root or _global fallback instead of taking the time to design a structure that really reflects what you're trying to do.
I'm genuinely curious why tooltips or textInput would need to manipulate the stage? Would a tooltip not just add a new temporary child to the item or item's parent, or a single-purpose tooltipContainer? If a textInput needs to listen for keyboard input, adding to the stage makes sense because otherwise getting those events depends on having keyboard focus.
For event based communication between display list branches, I'd reach no higher than the document class. And even that isn't always the best way. You could create some sort of EventManager which may or may not be a singleton (doesn't need to use stage, or even be a display object), which marshalls and dispatches event signals.
Could you give an example of some non-keyboard event that you'd want to listen for at the stage level?
-
When I put comments around the code in addEvent the code all runs and the trace statement works. When its uncommented I just get TypeError: Error #1009: Cannot access a property or method of a null object reference.
-
That code does look superficially correct.
I see an unmatched close } which makes me wonder if everything is matched up right. Are you sure that's the only place you're calling addEvent?
-
Yes, here is the whole thing. I only added addEvent in this one class
Actionscript Code:
package { import flash.display.*; import flash.events.*; public class Paddle extends MovieClip { var left:Boolean; var right:Boolean; var up:Boolean; var down:Boolean; var xPos:Number=-2; var yPos:Number=-2; function Paddle() { left=false; right=false; up=false; down=false; addEventListener(Event.ADDED_TO_STAGE, stageInit); } function stageInit(e:Event):void{ trace(e.target) addEvent() } function addEvent(){ this.focusRect=false; stage.focus=this; this.stage.addEventListener(KeyboardEvent.KEY_DOWN,keyUpHandler); this.stage.addEventListener(KeyboardEvent.KEY_UP,keyDownHandler); } public function keyDownHandler(e:KeyboardEvent):void { trace(e) if (e.keyCode==37) { left=true; } if (e.keyCode==39) { right=true; } } public function keyUpHandler(e:KeyboardEvent):void { if (e.keyCode==37) { left=false; } if (e.keyCode==39) { right=false; } } public function movePaddle() { if (left==true) { this.x-=10; } if (right==true) { this.x+=10; } } } }
-
Other than the fact that all your vars and functions should have public or private modifiers, that code looks correct. I can't see how stage could be null in addEvent. If you trace(stage) within addEvent and comment out the rest of addEvent, you get null?
-
Yes I get null. I know, it doesn't make sense.
-
It's certainly not obvious what's going wrong.
I'd add private or public modifiers and try again.
-
 Originally Posted by 5TonsOfFlax
It's certainly not obvious what's going wrong.
I'd add private or public modifiers and try again.
Just done that, no avail. Maybe it's a bug, although its a pretty massive big if so.
-
Using flashdevelop, I copied your code into a new project and tweaked it to compile (can't leave off the public/private in strict mode).
Code:
package {
import flash.display.*;
import flash.events.*;
public class Paddle extends MovieClip {
private var left:Boolean;
private var right:Boolean;
private var up:Boolean;
private var down:Boolean;
private var xPos:Number=-2;
private var yPos:Number=-2;
public function Paddle() {
left=false;
right=false;
up=false;
down=false;
addEventListener(Event.ADDED_TO_STAGE, stageInit);
}
private function stageInit(e:Event):void{
trace(e.target)
addEvent()
}
private function addEvent():void{
this.focusRect=false;
stage.focus=this;
this.stage.addEventListener(KeyboardEvent.KEY_DOWN,keyUpHandler);
this.stage.addEventListener(KeyboardEvent.KEY_UP, keyDownHandler);
addEventListener(Event.ENTER_FRAME, movePaddle);
}
public function keyDownHandler(e:KeyboardEvent):void {
trace(e)
if (e.keyCode==37) {
left=true;
}
if (e.keyCode==39) {
right=true;
}
}
public function keyUpHandler(e:KeyboardEvent):void {
if (e.keyCode==37) {
left=false;
}
if (e.keyCode==39) {
right=false;
}
}
public function movePaddle(e:Event = null):void {
if (left==true) {
this.x-=10;
}
if (right==true) {
this.x+=10;
}
}
}
}
And used it with this test document class:
Code:
package
{
import flash.display.Sprite;
import flash.events.Event;
/**
* ...
*/
public class Main extends Sprite
{
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
// entry point
var p:Paddle = new Paddle();
p.graphics.beginFill(0);
p.graphics.drawCircle(0, 0, 5);
p.graphics.endFill();
addChild(p);
}
}
}
I'm not seeing your error. I do see weird behavior regarding left and right.
-
Yes, I just added it directly from the document class (previously I was adding it from one displayobject down from doc class) and it traced the stage no problem. I guess it's something to do with the way I added it's parent maybe.
-
You know what? I just seen in the paddle's parent function in the constructor function before I even created a new paddle, the words paddle.addEvent(). Oops, sorry for wasting your time! I cannot remember doing that at all, I was surprised to find it.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|