22.2.3. 使用鼠标赋予一个对象焦点
正如用户可以使用Tab键或者方向键来分配焦点一样,用户也可以通过点击鼠标主按钮来分配焦点。但是,默认情况下,只有SimpleButton和 TextField 的实例可以通过鼠标点击获得焦点。如要通过点击赋予Spriteor MovieClip 实例焦点,我们使用下面之一的方法:
• 设置该实例的buttonMode属性为true (当不能确定它的tabEnabled属性没有明确地设置为false时)
• 设置该实例的tabEnabled属性为true
• 分配一个非负整数到这个实例的tabIndex变量(当不能确定它的tabEnabled属性没有明确地设置为false时)
比如,下面的代码创建了一个Sprite 对象并且当被点击的时候获得键盘焦点:
阻止一个对象从鼠标获得焦点,我们设置它的mouseEnabled属性为false。要阻止一个显示对象容器的所有子级从鼠标获得焦点,我们设置容器的mouseChildren属性为false。
NOTE
如果一个对象的mouseEnabled 设置为false 或者它的父级容器的mouseChildren属性为false,它无法通过鼠标获得焦点
此外,当Sprite, MovieClip, or SimpleButton的tabEnabled属性明确被设置为false时,这个实例也不能从鼠标获得焦点。同样地,当他们的父级容器的tabChildren属性为false, 他们也无法从鼠标获得焦点。但是,由于Flash Player 的bug,一个tabEnabled属性或者父级容器的tabChildren 属性被明确设置为false 的TextField对象依然可以通过鼠标获得焦点。(这BUG现在没了)
22.2.3.1.通过单一的父级操作子级的焦点
要命令ActionScript 把一个显示对象容器以及它的所有子级都看做一个可以通过点击一次鼠标获得焦点的组,遵循下面步骤:
1. 通过设置容器的buttonMode 或tabEnabled 属性为true 或者设置它的tabIndex 属性值为非负整数以允许其基于鼠标获得焦点。
2. 通过设置容器的mouseChildren 属性为false 以废掉该容器所有子级对象的鼠标交互能力。
22.2.4. Flash Player的焦点事件
当一个应用程序的键盘焦点变化到一个新的对象(前面3节介绍的)上,Flash Player会发送一个或更多的描述这次变化的焦点事件。Table 22-2 列出了 Flash Player的内置焦点事件的类型。每种事件中, "事件类型" 一栏列出了FocusEvent类的描述事件类型的正式字符串常量, "描述" 一栏描述了这个事件代表的用户操作。"目标"一栏列出了这个事件派送的目标,"默认行为" 一栏列出了Flash Player对这个事件的原生反应。"冒泡"一栏列出该事件是否支持冒泡阶段。最后, "传递给侦听器函数的数据类型" 一栏列出了传递给事件处理函数的对象的数据类型。
Table 22-2. Flash Player 焦点事件
事件类型
描述
目标
默认行为
冒泡
传递给侦听器函数的数据类型
FocusEvent.FOCUS_IN
给定对象获得焦点
获得焦点的对象
(用FocusEvent 类的实例属性
relatedObject 可访问丢失焦点的那个对象)
无
是
FocusEvent
FocusEvent.FOCUS_OUT
给定对象丢失焦点
丢失焦点的对象
(用FocusEvent 类的实例属性
relatedObject 可访问获得焦点的那个对象)
无
是
FocusEvent
FocusEvent.KEY_FOCUS_CHANGE
用户试图通过键盘改变焦点之后
当前焦点的对象
(用FocusEvent 类的实例属性
relatedObject 可访问用户试图使其焦点的那个对象)
Flash Player 改变焦点,可以被Event 类的实例方法preventDefault() 取消
是
FocusEvent
FocusEvent.MOUSE_FOCUS_CHANGE
用户试图通过鼠标改变焦点之后
同上
同上
是
FocusEvent
如Table 22-2 所示, FocusEvent.FOCUS_IN 和 FocusEvent.FOCUS_OUT事件用来探测一个对象得失焦点。在这2个事件被派送的时候,焦点已经发生了改变。但是相反地,
FocusEvent.KEY_FOCUS_CHANGE 和 FocusEvent.MOUSE_FOCUS_CHANGE事件用来检测一个对象准备得失焦点,但是这时候得失还没有发生。应用程序一般使用FocusEvent.KEY_FOCUS_CHANGE和FocusEvent.MOUSE_FOCUS_CHANGE 事件来阻止用户通过键盘、鼠标改变焦点,以强制用户于界面的一个特定部件进行交互,比如一个强制回应对话框。
通过鼠标事件, Flash Player 定义了非真正全局化的事件。但是通过侦听舞台实例的焦点事件,我们可以处理所有发生在Flash Playe内的焦点改变事件。Example22-7 展示了这个技巧,它是一个创建了2个TextField 对象的应用程序,并设置当它们获得焦点的时候背景色变为绿色。
Example 22-7. “全局地”处理焦点事件
焦点事件可以被注册在事件目标上的或者其父级对象上的侦听器处理。Example22-8 显示了一个程序,它创建了一个一旦收到焦点,在输入至少3个字符之前无法丢失焦点的文本框。
Example 22-8. 为一个特定对象处理焦点事件
22.3. 键盘输入事件
Flash Player 当用户按下键盘按钮的时候派送一个键盘输入事件。 广义来说,键盘输入事件被用于引发一个对应用程序的应答,这个程序可能一个整体或者只是界面中的一个特定元素。比如,按下S键可能会引发一个全局的“保存用户数据”指令而按“下”方向键可能选择特定的一个菜单组件。
引发应用程序级别的指令的键盘输入事件代表性地被“全局地”处理,通过注册在FP舞台实例上的侦听器。但是相对地,引发界面某个元素的响应的键盘输入事件通常被注册在当前具有键盘焦点的对象上的侦听器处理。
Flash Player'的键盘输入事件被用做键盘控制程序的拓展,但是不支持对TextField对象的文本输入的响应。想要响应文本输入,使用TextEvent.TEXT_INPUT 事件,z 在"Text-Input Events."
Table22-3 列出了Flash Player'的内置键盘输入事件的种类。每种事件中, "事件类型" 一栏列出了KeyboardEvent类的描述事件类型的正式字符串常量, "描述" 一栏描述了这个事件代表的用户操作。"目标"一栏列出了这个事件派送的目标,"默认行为" 一栏列出了Flash Player对这个事件的原生反应。不像鼠标事件和焦点事件,键盘事件没有默认行为。"冒泡"一栏列出该事件是否支持冒泡阶段。最后, "传递给侦听器函数的数据类型" 一栏列出了传递给事件处理函数的对象的数据类型。
注意,键盘事件只有在flashplayer获得系统焦点的情况下才会发生派送。想要得知FP什么时候得失系统焦点,注册Event.ACTIVATE和 Event.DEACTIVATE事件 (在"Flash Player-Level Input Events."中介绍)
事件类型
描述
目标
默认行为
冒泡
传递给侦听器的参数类型
KeyboardEvent.KEY_DOWN
按下键盘
当前拥有焦点的(InteractiveObject)交互对象,若无,则为Stage实例
无
是
KeyboardEvent
KeyboardEvent.KEY_UP
释放键盘
当前拥有焦点的(InteractiveObject)交互对象,若无,则为Stage实例
无
是
KeyboardEvent
22.3.1. "全局地"处理键盘事件
相对于鼠标和焦点事件, Flash Player没有定义真正的全局键盘事件。但是,通过为舞台实例注册键盘侦听,我们可以处理所有键盘交互,只要当前Flash Player 拥有系统焦点。Example22-9 证明了这个技术,它展示了一个简单的类,当按下键盘的时候显示调试信息。
Example 22-9. "全局地"处理键盘事件
package {
import flash.display.*;
import flash.events.*;
public class GlobalKeyboardSensor extends Sprite {
public functionGlobalKeyboardSensor () {
//注册以侦听键盘按下
stage.addEventListener(KeyboardEvent.KEY_DOWN,keyDownListener);
}
// 当FP拥有系统焦点且键盘按下,会调用这个函数
private function keyDownListener (e:KeyboardEvent):void {
trace("A key waspressed.");
}
}
}
22.3.2.处理特定对象的键盘事件
如Table 22-3描述的,当没有对象具有焦点时,舞台实例就成为键盘事件派送的目标。但是反过来,当一个InteractiveObject实例具有键盘焦点,这个实例就成为键盘事件派送的目标。因此,要响应一个指向特定对象的键盘输入,我们在它上面注册侦听器。Example 22-10 证明了这点,它展示了一个应用程序,创建了2个Sprite 对象, rect1和 rect2. 当 rect1 获得焦点且键盘按下时,程序使rect1右移。当rect2获得焦点且键盘按下时,程序旋转rect2.
Example 22-10.为一个特定对象处理键盘事件
现在我们知道如何探测用户是否按下或释放一个键盘按键了,让我们再来探索是哪个键被按下或释放。
22.3.3. 判断最近按下/释放的一个键
Flash Player 分配一个专门的标识符给所有键盘上的按键,称为keycode。要分别最近按下或释放的按键,我们在KeyboardEvent.KEY_UP或者KeyboardEvent.KEY_DOWN的侦听器函数中检索KeyboardEvent类实例属性keyCode。如Example 22-11所示。
Example 22-11. Retrieving a pressed key's key code
private function keyDownListener(e:KeyboardEvent):void {
// 输出按下的键的key code
keyoutput.text = "The key code for the key you pressed is:"
+ e.keyCode;
}
要分辨这个按下或释放的键是哪个,我们在侦听器中比较这个键的Code值和KeyboardEvent类的实例属性keyCode。比如,下面的KeyboardEvent.KEY_DOWN 侦听器函数通过比较keyCode值是否为27来判断按下的键是否是Escape键.
private function keyDownListener(e:KeyboardEvent):void {
if (e. keyCode== 27) {
trace("The ESC key was pressed");
}
}
所有的控制键和数字小键盘键都可以通过flash.ui.Keyboard 类中的常量来访问。因此,前面的代码可以写成
(使用Keyboard 类的静态属性ESCAPE 代替了数字值27):
if (e.keyCode== Keyboard.ESCAPE) {
Key codes 依托于语言和OS.
NOTE
US英文键盘的keycode清单,请看: http://livedocs.macromedia.com/flash/8/main/00001686.html.
当书写未包含在flash.ui.Keyboard 常量中的键的表达式时,我们采用下面步骤:
1. 在电脑的OS和目标用户的键盘上运行Example 22-11的KeyViewer程序。
2. 按下渴望的键
3. 把被返回的key code记录进一个常量.
4. 使用第3步中的常量来判断这个渴望的键的按下或释放。
比如,假设我们希望判断在微软OS、美国英文键盘上按下的“A”键。我们运行KeyViewer,然后按下"A" 键。作为回应,KeyViewer 应用程序显示这个key code 65. 然后我们在一个自定义类的常量中记录这个key code,比如命名为KeyConstants, 如下:
public static const A_KEY:int = 65;
然后,要判断“A”键的按下,我们使用下面的代码:
private function keyDownListener(e:KeyboardEvent):void {
if (e.keyCode == KeyConstants.A_KEY) {
trace("The A key was pressed");
}
}
下面的代码在一个非常简单的测试程序的上下文中展示了这种技巧:
package {
import flash.display.*;
import flash.events.*;
public class AKeySensor extends Sprite {
public static const A_KEY:int = 65;
public function AKeySensor () {
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownListener);
}
private function keyDownListener (e:KeyboardEvent):void {
if (e.keyCode == AKeySensor.A_KEY) {
trace("The A key was pressed");
}
}
}
}
注意,当一个IME(输入法编辑器)在启用的时候, KeyboardEvent类的实例属性keyCode 是不被支持的。有关IMEs的信息,看ADOBE AS 语言参考和Adobe's ProgrammingActionScript 3.0的FP APIs—— 客户端系统环境——IME类。