java action的替用品
正如早先指出的那样,action()并不是我们对所有事举办分类后自动为handleEvent()挪用的独一要领。有三个其它的被挪用的要领集,假如我们想捕获某些范例的事件(键盘、鼠标和核苦衷件),因此我们不得不外载划定的要领。这些要领是界说在基本类组件里,所以他们险些在所有我们大概安顿在窗体中的组件中都是有用的。然而,我们也留意到这种要领在Java 1.1版中是不被支持的,同样尽量我们大概留意到担任代码操作了这种要领,我们将会利用Java 1.1版的要领来取代(本章后头有具体先容)。
组件要领 何时挪用
action(Event evt, Object what) 当典范的事件针对组件产生(譬喻,当按下一个按钮或下拉列表项目被选中)时挪用
keyDown(Event evt, int key) 当按键被按下,组件拥有核心时挪用。第二个自变量是按下的键而且是冗余的是从evt.key处复制来的
keyup(Event evt, int key) 当按键被释放,组件拥有核心时挪用
lostFocus(Event evt, Object what) 核心从方针处移开时挪用。凡是,what是从evt.arg里冗余复制的
gotFocus(Event evt, Object what) 核心移动到方针时挪用
mouseDown(Event evt, int x,int y) 一个鼠标按下存在于组件之上,在X,Y座标处时挪用
mouseUp(Event evt, int x, int y) 一个鼠标升起存在于组件之上时挪用
mouseMove(Event evt, int x, int y) 当鼠标在组件上移动时挪用
mouseDrag(Event evt, int x, int y) 鼠标在一次mouseDown事件产生后拖动。所有拖动事件城市陈诉给内部产生了mouseDown事件的谁人组件,直到碰着一次mouseUp为止
mouseEnter(Event evt, int x, int y) 鼠标从前不在组件上方,但今朝在
mouseExit(Event evt, int x, int y) 鼠标曾经位于组件上方,但今朝不在
当我们处理惩罚非凡环境时——一个鼠标事件,譬喻,它刚好是我们想获得的鼠标事件存在的座标,我们将看到每个措施吸收一个事件连同一些我们所需要的信息。有趣的是,当组件的handleEvent()挪用这些要领时(典范的事例),附加的自变量老是多余的因为它们包括在事件工具里。事实上,假如我们调查component.handleEvent()的源代码,我们能发明它显然将增加的自变量抽失事件工具(这大概是思量到在一些语言中无效率的编码,但请记着Java的核心是安详的,不必担忧。)试验对我们表白这些事件事实上在被挪用而且作为一个有趣的实验是值得建设一个过载每个要领的措施片,(action()的过载在本章的其它处所)当事件产生时显示它们的相关数据。
这个例子同样向我们展示了奈何制造本身的按钮工具,因为它是作为方针的所有事件权益来利用。我大概会首先(也是必需的)假设制造一个新的按钮,我们从按钮处担任。但它并不能运行。取而代之的是,我们从画布组件处(一个很是普通组件)担任,并在其上不利用paint()要领画出一个按钮。正如我们所看到的,自从一些代码混入到画按钮中去,按钮基础就不运行,这实在是太糟糕了。(假如您不相信我,试图在例子中为画布组件互换按钮,请记着挪用称为super的基本类构建器。我们会看到按钮不会被画出,事件也不会被处理惩罚。)
myButton类是明晰说明的:它只和一个自动事件(AutoEvent)“父窗口”一起运行(父窗口不是一个基本类,它是按钮建设和存在的窗口。)。通过这个常识,myButton大概进入到父窗口而且处理惩罚它的文字字段,一定就能将状态信息写入到父窗口的字段里。虽然这是一种很是有限的办理要领,myButton仅能在连结AutoEvent时被利用。这种代码有时称为“高度团结”。可是,制造myButton更需要许多的不是为例子(和大概为我们将写的一些措施片)包管的尽力。再者,请留意下面的代码利用了Java 1.1版不支持的API。
//: AutoEvent.java // Alternatives to action() import java.awt.*; import java.applet.*; import java.util.*; class MyButton extends Canvas { AutoEvent parent; Color color; String label; MyButton(AutoEvent parent, Color color, String label) { this.label = label; this.parent = parent; this.color = color; } public void paint(Graphics g) { g.setColor(color); int rnd = 30; g.fillRoundRect(0, 0, size().width, size().height, rnd, rnd); g.setColor(Color.black); g.drawRoundRect(0, 0, size().width, size().height, rnd, rnd); FontMetrics fm = g.getFontMetrics(); int width = fm.stringWidth(label); int height = fm.getHeight(); int ascent = fm.getAscent(); int leading = fm.getLeading(); int horizMargin = (size().width - width)/2; int verMargin = (size().height - height)/2; g.setColor(Color.white); g.drawString(label, horizMargin, verMargin + ascent + leading); } public boolean keyDown(Event evt, int key) { TextField t = (TextField)parent.h.get("keyDown"); t.setText(evt.toString()); return true; } public boolean keyUp(Event evt, int key) { TextField t = (TextField)parent.h.get("keyUp"); t.setText(evt.toString()); return true; } public boolean lostFocus(Event evt, Object w) { TextField t = (TextField)parent.h.get("lostFocus"); t.setText(evt.toString()); return true; } public boolean gotFocus(Event evt, Object w) { TextField t = (TextField)parent.h.get("gotFocus"); t.setText(evt.toString()); return true; } public boolean mouseDown(Event evt,int x,int y) { TextField t = (TextField)parent.h.get("mouseDown"); t.setText(evt.toString()); return true; } public boolean mouseDrag(Event evt,int x,int y) { TextField t = (TextField)parent.h.get("mouseDrag"); t.setText(evt.toString()); return true; } public boolean mouseEnter(Event evt,int x,int y) { TextField t = (TextField)parent.h.get("mouseEnter"); t.setText(evt.toString()); return true; } public boolean mouseExit(Event evt,int x,int y) { TextField t = (TextField)parent.h.get("mouseExit"); t.setText(evt.toString()); return true; } public boolean mouseMove(Event evt,int x,int y) { TextField t = (TextField)parent.h.get("mouseMove"); t.setText(evt.toString()); return true; } public boolean mouseUp(Event evt,int x,int y) { TextField t = (TextField)parent.h.get("mouseUp"); t.setText(evt.toString()); return true; } } public class AutoEvent extends Applet { Hashtable h = new Hashtable(); String[] event = { "keyDown", "keyUp", "lostFocus", "gotFocus", "mouseDown", "mouseUp", "mouseMove", "mouseDrag", "mouseEnter", "mouseExit" }; MyButton b1 = new MyButton(this, Color.blue, "test1"), b2 = new MyButton(this, Color.red, "test2"); public void init() { setLayout(new GridLayout(event.length+1,2)); for(int i = 0; i < event.length; i++) { TextField t = new TextField(); t.setEditable(false); add(new Label(event[i], Label.CENTER)); add(t); h.put(event[i], t); } add(b1); add(b2); } } ///:~
#p#分页标题#e#
我们可以看到构建器利用操作自变量同名的要领,所以自变量被赋值,而且利用this来区分:
this.label = label;
paint()要领由简朴的开始:它用按钮的颜色填充了一个“圆角矩形”,然后画了一个黑线环绕它。请留意size()的利用抉择了组件的宽度和长度(虽然,是像素)。这之后,paint()看起来很是的巨大,因为有大量的预测去计较出奈何操作“font metrics”会合按钮的标签到按钮里。我们能获得一个相当好的关于继承存眷要领挪用的主意,它将措施中那些相当平凡的代码挑出,当我们想会合一个标签到一些组件里时,我们正好可以对它举办剪切和粘贴。
您直到留意到AutoEvent类才气正确地领略keyDown(),keyUp()及其它要领的运行。这包括一个Hashtable(译者注:散列表)去节制字符串来描写关于事件处理惩罚的事件和TextField范例。虽然,这些能被静态的建设而不是放入Hashtable但我认为您会同意它是更容易利用和改变的。出格是,假如我们需要在AutoEvent中增加或删除一个新的事件范例,我们只需要简朴地在事件排队中增加或删除一个字符串——所有的事情都自动地完成了。
我们查出在keyDown(),keyup()及其它要领中的字符串的位置回到myButton中。这些要领中的任何一个都用父句柄试图回到父窗口。父类是一个AutoEvent,它包括Hashtable h和get()要领,当拥有特定的字符串时,将对一个我们知道的TextField工具发生一个句柄(因此它被选派到那)。然后事件工具修改显示在TextField中的字符串告诉。从我们可以真正留意到举出的例子在我们的措施中运行事件时以来,可以发明这个例子运行起来颇为有趣的。