Flash 在我将阶段引用到菜单类后,键盘事件未触发
我对我从中学习的菜单教程有问题。我已经完成并使用了该网站的大部分教程(如果不是全部的话) 无论如何,我的问题是他们的基本菜单类Flash 在我将阶段引用到菜单类后,键盘事件未触发,flash,actionscript-3,Flash,Actionscript 3,我对我从中学习的菜单教程有问题。我已经完成并使用了该网站的大部分教程(如果不是全部的话) 无论如何,我的问题是他们的基本菜单类 package com.game.scripts.menu { import flash.display.MovieClip; import flash.display.Stage; import flash.events.Event; import com.caurina.transitions.Tweener; publi
package com.game.scripts.menu
{
import flash.display.MovieClip;
import flash.display.Stage;
import flash.events.Event;
import com.caurina.transitions.Tweener;
public class BaseMenu extends MovieClip
{
public var stageRef:Stage;
public var loadNext:BaseMenu;
public function BaseMenu()
{
alpha = 0;
}
public function Unload(loadMe:BaseMenu = null):void
{
if(loadMe != null)
{
loadNext = loadMe;
}
Tweener.addTween(this, {alpha:0, time:0.7, onComplete:Remove});
}
public function Remove():void
{
//dispatchEvent(new Event("menuRemoved"));
if(stageRef.contains(this))
{
stageRef.removeChild(this);
}
if(loadNext != null)
{
loadNext.Load();
}
}
public function Load():void
{
stageRef.addChild(this);
Tweener.addTween(this, {alpha:1, time:0.7});
}
}
}
每当我使用Remove函数时(卸载函数也使用该函数),我的stage.addEventListeners就会中断。特别是我的stage.addEventListenerKeyboardEvent.KEY_UP,另一个类中的KeyUpHandler根本不执行
有没有其他方法可以在不破坏舞台的情况下删除菜单?或者如果你知道一个更好的菜单教程,一个链接将不胜感激:D
编辑
我刚刚对Remove函数中的所有内容进行了注释,但密钥处理程序仍然不起作用
编辑2
第一次编辑只适用于我的主菜单,我的其他菜单似乎很好。我评论了这一部分
if(stageRef.contains(this))
{
stageRef.removeChild(this);
}
我的键盘处理器工作正常。因此,我假设flash不会为我删除movieclips,或者我会没事,它会被删除吗?我只能猜测,在调用remove之后,您为stageRef提供给菜单类的精灵没有引用,因此会被垃圾收集,因此您不再获得任何关键事件 两项建议: 确保为stageRef设置了适当的值 确保您在键盘侦听器中使用了强引用,以确保舞台未被清理。
编辑:想想看,如果你的基本菜单是从sprite或MovieClip派生出来的,我敢肯定你不需要这样做。所以只需将stageRef.removeChild更改为stage.removeChild 你的舞台并没有指向真正的舞台。有点 你也应该试着习惯使用添加到舞台上的活动
package src
{
import flash.display.Sprite;
import flash.events.Event;
public class MainDocument extends Sprite
{
private var myMenus:BaseMenu;
public function MainDocument()
{
addEventListener(Event.ADDED_TO_STAGE, initMain);
}
private function initMain(e:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, initMain);
myMenus = new BaseMenu();
addChild(myMenus);
}
}
}
package src
{
import flash.display.Sprite;
import flash.events.Event;
public class BaseMenu extends Sprite
{
public function BaseMenu()
{
addEventListener(Event.ADDED_TO_STAGE, initBanseMenu);
}
private function initBanseMenu(e:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, initBanseMenu);
trace(stage.stageHeight);
}
}
}
从跟踪中可以看到,无需引用即可访问阶段
这也应该很好。实际上,stage是“stage”而不是“stage”,因此请确保将“stage”发送给BaseMenu构造函数
public var stageRef:Stage;
public function BaseMenu(stageRef:Stage)
{
this.stageRef = stageRef;
alpha = 0;
}
好的,在这里,您可以将这些文件放在flashdevelop项目或任何您使用的项目中,并对其进行测试;-
package src
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
public class MainDocument extends Sprite
{
public var myMenuTest:BaseMenu;
public var mySubMenuTest:SubMenu;
public function MainDocument()
{
addEventListener(Event.ADDED_TO_STAGE, initMain);
}
private function initMain(e:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, initMain);
myMenuTest = new BaseMenu(stage);
myMenuTest.x = stage.stageWidth / 2;
myMenuTest.y = stage.stageHeight / 2;
//myMenuTest.Load(); // we can load our Main menu now if we want.
mySubMenuTest = new SubMenu(stage);
mySubMenuTest.x = 100;
mySubMenuTest.y = 100;
stage.addEventListener(KeyboardEvent.KEY_UP, handleKeyUp);
}
// for testing purposes.
private function handleKeyUp(e:KeyboardEvent):void
{
if (e.keyCode == Keyboard.UP)
myMenuTest.Unload(mySubMenuTest);
else if (e.keyCode == Keyboard.DOWN)
mySubMenuTest.Unload(myMenuTest);
else
trace(e.keyCode);
}
}
}
package src
{
import flash.display.Sprite;
import flash.display.Stage;
public class BaseMenu extends Sprite
{
public var stageRef:Stage;
public var loadNext:BaseMenu;
public function BaseMenu(stageRef:Stage)
{
this.stageRef = stageRef;
}
public function Unload(loadMe:BaseMenu = null):void
{
if (loadMe != null)
{
loadNext = loadMe;
}
Remove(); // add your tween.
}
public function Load():void
{
// this is just so we can have something to see for the test.
drawTest();
stageRef.addChild(this);
// add your tween
}
public function Remove():void
{
if (stageRef.contains(this))
stageRef.removeChild(this);
if (loadNext != null)
loadNext.Load();
}
protected function drawTest():void
{
graphics.clear();
graphics.lineStyle(1, 0);
graphics.beginFill(0xccccff);
graphics.drawCircle(0, 0, 20);
graphics.endFill();
}
}
}
package src
{
import flash.display.Stage;
public class SubMenu extends BaseMenu
{
public function SubMenu(stageRef:Stage)
{
super(stageRef);
}
}
}
这应该可以解释我的意思是如何起作用的。
要测试这个程序,只需在调试模式下加载它,并使用向上或向下箭头键在两个菜单类之间切换。无论菜单是什么,按任何其他键都会将键代码跟踪到标准输出。调试输出窗口。
显然每个文件有一个类。
希望这能澄清问题。这是一个相当糟糕的教程。这是一个关于构建完整游戏的非常好的例子。我终于解决了这个问题。出于某种原因,除非我在加载新菜单后单击屏幕,否则key-up处理程序不会注册。基本菜单构造函数不接受参数,因为扩展基本菜单的类会得到一个错误,因为它们的构造函数带有stage参数。Event.ADDED_TO_STAGE已在我的main.as文件中使用。我是否需要在每个类中执行该检查?使用ADDED_TO_STAGE将确保在您尝试使用它之前,舞台上确实存在某些内容。这通常不是问题,但如果您不小心,可能会出现一些难以调试的问题。必须以某种方式引用stageRef。你不能只说var stageRef:Stage它必须指向某个东西。最快的方法是在创建对象时发送该引用。扩展BaseMenu的所有内容也需要有该引用。如果你走另一条路,使用added_to_stage,因为baseMenu扩展了Sprite/MovieClip,它已经有了一个与我上面的stage类似的stage的内部引用。stage heights这是你唯一可以对stage进行干净引用的两个选项。我知道我试图对BaseMenu类进行更改,但从扩展菜单类得到了一个空引用。如果我按照你建议的方式做,我会重做整个菜单系统。我更新了我的问题,指出我使用stageRef删除菜单的if语句是问题所在,是否有方法继续删除它,或者有其他方法删除movieclip。强引用是什么意思?addEventListener中的第5个参数是UseWeakRaference:Boolean,如果您将其设置为false,那么您将获得一个强引用,从而确保您正在侦听的对象在侦听时也不会被垃圾收集:为密钥处理程序提供一个强引用仍然不能解决问题。我真的不明白的是,为什么只有键处理程序受到影响,其他一切似乎都正常工作。