在Visual Basic这样的措辞中,事宜与代码之间的对应是明确的。程序员对干系的特定事宜编写代码,并将这些代码放置在过程中,常日人们将它们称为事宜过程(event procedure)。例如,有一个名为HelpButton的Visual Basic按钮有一个与之关联的HelpButton_Click事宜过程。这个过程中的代码将在点击按钮后实行。每个Visual Basic的GUI组件都相应一个固定的事宜集,不可能改变Visual Basic组件相应的事宜集。
另一方面,如果利用像原始的C这样的措辞进行事宜驱动的程序设计,就须要编写代码来不断地检讨事宜行列步队,以便查询操作环境报告的内容。(常日这些代码被放置在包含很多switch语句的循环体中)。显然,这种办法编写的程序可读性很差,而且在有些情形下,编码的难度也非常大。它的好处在于相应的事宜不受限定,而不像Visual Basic这样的措辞,将事宜行列步队对程序员隐蔽起来。
Java程序设计环境折中了Visual Basic与原始C的事宜处理办法,因此,它既有着强大的功能,又具有一定的繁芜性。在AWT所知的事宜范围内,完备可以掌握事宜从事宜源(event source)例如按钮或滚动条,到事宜监听器(event listener)的通报过程,并将任何工具指派给事宜监听器。不过事实上,该当选择一个能够便于相应事宜的工具。这种事宜委托模型(event delegationmodel)与Visual Basic那种预定义监听器模型比较起来更加灵巧,但却须要编写更多的代码,整理起来也非常困难(至少在熟习它之前)。
事宜源有一些向其注册事宜监听器的方法。当某个事宜源产生事宜的时候,事宜源会向为事宜注册的所有事宜监听器工具发送一个通知布告。
像Java这样的面向工具措辞,都将事宜的干系信息封装在一个事宜工具中。在Java中,所有的事宜工具都终极派生于java.util.EventObject类。当然,每个事宜类型还有子类,例如,ActionEvent和WindowEvent。
不同的事宜源可以产生不同类别的事宜。例如,按钮可以发送一个ActionEvent工具,而窗口可以发送WindowEvent工具。
综上所述,下面给出AWT事宜处理机制的概要:
• 监听器工具是一个实现了特定监听器接口(listener interface)的类的实例。
• 事宜源是一个能够注册监听器工具并发送事宜工具的工具。
• 当事宜发生时,事宜源将事宜工具通报给所有注册的监听器。
• 监听器工具将利用事宜工具中的信息决定如何对事宜做出相应。
可以采取下列代码模型来为事宜源工具注册监听器工具:
eventSourceObject.addEventListener(eventListenerObject);
下面是一个例子:
ActionListener listener = . . .;
JButton button = new JButton("Ok");
button.addActionListener(listener);
现在,只要按钮产生了一个“动作事宜”,listener工具就会得到通知布告。对付按钮来说,动作事宜便是点击按钮。
上面的代码哀求监听器工具所属的类必须实现相应的接口(在这个例子中是ActionListener接口)。
与Java中所有的接口一样,实现一个接口就意味着要用完备相同的署名实现每个方法。为了实现ActionListener接口,监听器类必须有一个被称为actionPerformed的方法,该方法吸收一个ActionEvent工具参数。
只要用户点击按钮,JButton工具就会创建一个ActionEvent工具,然后调用listener.actionPerformed(event) 通报事宜工具。可以将多个监听器工具添加到一个像按钮这样的事宜源中。这样一来,只要用户点击按钮,按钮就会调用所有监听器的actionPerformed方法。
图8-1显示了事宜源、事宜监听器和事宜工具之间的协作关系。
实例:处理按钮点击事宜
为了加深对事宜委托模型的理解,下面以一个相应按钮点击事宜的大略例子来解释所须要知道的所有细节。在这个例子中,我们想要
• 在一个面板中放置三个按钮。
• 添加三个监听器工具用来作为按钮的动作监听器。
在这个情形下,只要用户点击面板上的任何一个按钮,干系的监听器工具就会吸收到一个ActionEvent工具,它表示有个按钮被点击了。在示例程序中,监听器工具将改变面板的背景颜色。
在演示如何监听按钮点击事宜之前,首先须要讲解一下如何创建按钮以及如何将它们添加到面板中。(有关GUI元素更加详细的内容请参阅第9章。)
可以通过在按钮布局器中指定一个标具名符串、一个图标或两项都指定来创建一个按钮。
下面是两个例子:
将按钮添加到面板中须要调用add方法(十分随意马虎影象)。add方法的参数指定了将要放置到容器中的组件。例如,
图8-2显示了却果。
至此,知道了如何将按钮添加到面板上,接下来须要增加让面板监听这些按钮的代码。这须要一个实现了ActionListener接口的类,如前所述,它该当包含一个actionPerformed方法,其署名为:
public void actionPerformed(ActionEvent event)
把稳:在按钮例子中利用的ActionListener接口并不仅限于按钮点击事宜。它可以运用于很多情形:
• 当采取鼠标双击的办法选择了列表框中的一个选项时。
• 当选择一个菜单项时。
• 当在文本域中敲击ENTER键时。
• 对付一个Timer组件来说,当到达指定的韶光间隔时。
在本章和下一章中,将会看到更加详细的内容。
在各种情形下,利用ActionListener接口的办法都是一样的:actionPerformed方法(ActionListener中的唯一方法)将吸收一个ActionEvent类型的工具作为参数。这个事宜工具包含了事宜发生时的干系信息。
当按钮被点击时,我们希望将面板的背景颜色设置为指定的颜色。该颜色存储在监听器类中。
然后,为每种颜色布局一个工具,并将这些工具设置为按钮监听器。
例如,如果一个用户在标有“Yellow”的按钮上点击了一下,那么yellowAction工具的actionPerformed方法就会被调用。这个工具的backgroundColor实例域设置为Color.YELLOW,现在就将面板的背景色设置为黄色了。
这里还有一个须要考虑的问题。ColorAction工具没有权限访问panel变量。可以采取两种办法办理这个问题。一个是将面板存储在ColorAction工具中,并在ColorAction布局器中设置它;另一个是将ColorAction作为ButtonPanel类的内部类。这样一来,ColorAction就自动地拥有访问外部类的权限了(有关内部类的详细先容请参阅第6章)。
这里利用第二种方法。下面解释一下如何将ColorAction类放置在ButtonPanel类中。
下面仔细地研究一下actionPerformed方法。在ColorAction类中没有setBackground方法,但在外部ButtonPanel类中却有。这个方法可以在ButtonPanel工具布局内部工具之后调用。(再次解释一下,outer不是Java程序设计措辞的关键字,它只是一种表示符号,用于表示内部类工具不可见的外部类引用。)
这种环境十分常见。事宜监听器工具常日须要实行一些对其他工具可能产生影响的操作。
可以策略性地将监听器类放置在须要修正状态的那个类中。
例8-1包含完全的程序。无论何时点击任何一个按钮,对应的动作监听器都会修正面板的背景颜色。
例8-1 ButtonTest.java
javax.swing.JButton 1.2
• JButton(String label)
布局一个按钮。标签可以是常规的文本,从JDK 1.3开始,也可以是HTML。例如,"<html><b>Ok</b></html>"。
参数:label 显示在按钮表面的文本
• JButton(Icon icon)
布局一个按钮。
参数:icon 显示在按钮表面的图标
• JButton(String label, Icon icon)
布局一个按钮。
参数:label 显示在按钮表面的文本
icon 显示在按钮表面的图标
java.awt.Container 1.0
• Component add(Component c)
将组件c添加到容器中。
javax.swing.ImageIcon 1.2
• ImageIcon(String filename)
布局一个图标,它的图像存储在一个文件中。通过媒体跟踪器自动地加载这个图像(参阅第7章)。
建议利用内部类
有些人不喜好利用内部类,其缘故原由是以为类和工具的增殖会使得程序的实行速率变慢。下面让我们谈论一下这个问题。首先,不须要为每个用户界面组件定义一个新类。在前面列举的例子中,三个按钮共享同一个监听器类。当然,每个按钮分别利用不同的监听器工具。但是,这些工具并不大,它们只包含一个颜色值和一个面板的引用。而利用传统的if. . .else语句的办理方案也须要引用动作监听器存储的上述颜色工具,只不过这是一个局部变量,而不是实例域。
我们认为现在已经到了习气利用内部类的时期了。我们建议为事宜处理设计一个专门的内部类;而不要将一个已经存在的类转换为监听器,纵然匿名内部类也有一定的运用市场。
下面是一个解释利用匿名内部类简化代码的例子。如果仔细看一下例8-1的代码,就会把稳到每个按钮的处理过程都是一样的:
1)用标具名符串布局按钮。
2)将按钮添加到面板上。
3)用适当的颜色布局一个动作监听器。
4)添加动作监听器。
为了简化这些操作过程,可以设计一个赞助方法:
然后将ButtonPanel布局器简化为:
接着可以进一步简化。请把稳,ColorAction类只在makeButton方法中用到一次。因此,可以将它设计为一个匿名类:
动作监听器代码现在变得更加大略了。actionPerformed方法仅仅引用参数变量backgroundColor。
(与内部类中访问的所有局部变量一样,该当将参数声明为final。)
这里不须要显式的布局器。在第6章中已经看到,内部类机制将自动地天生一个布局器,个中存储着所有用在内部类方法中的final局部变量。
提示:匿名内部类看起来可能让人觉得有些困惑。如果演习自己的眼睛能够捕捉程序代码中的关键字,就可以破解它们,例如:
这便是说,按钮动作设置背景颜色。只要事宜处理器包含的语句条数不多,就认为这段代码的可读性还是不错的,尤其是在对内部类机制没有什么抵触生理的情形下。
提示:在JDK 1.4中引入了不该用内部类定义大略的事宜监听器的机制。例如,假设有一个标签为Load的按钮,它的事宜处理只包含下面一个方法调用:
frame.loadData( );
当然,可以利用匿名内部类:
但是,EventHandler类可以利用下列调用,自动地创建这样一个监听器:
当然,仍旧须要安装处理器:
这里的类型转换是必要的,由于create方法返回的是一个Object。有可能在JDK未来的版本中利用泛型类型,这样可以使得这个方法变得更加方便。
如果事宜监听器调用的方法只包含一个从事宜处理器继续来的参数,就可以利用其余一种形式的create方法。例如,调用:
等价于
须要把稳,事宜处理器将属性source和text的名字转换成符合JavaBeans习气的方法调用getSource和getText。(有关属性和JavaBeans组件更加详细的论述请参阅卷II。)
然而,在实际中,这种环境并不常见,而且也没有相应的机制能够处理那些不是由事宜工具继续而来的参数。
将组件变成事宜监听器
任何实现了ActionListener接口的类工具都可以作为按钮监听器。我们更加方向于为将要实行的按钮动作创建一个新类和该类的工具。然而,有些程序员不愿意利用内部类,而是选择了不同的策略。他们找到因事宜而改变的组件,然后让这些组件实现ActionListener接口,并增加actionPerformed方法。不才面的例子中,可以将ButtonPanel 转换为动作监听器:
然后,将面板本身设置为三个按钮的监听器:
yellowButton.addActionListener(this);
blueButton.addActionListener(this);
redButton.addActionListener(this);
把稳,现在这里的三个按钮不再是独立的监听器。它们共享一个监听器工具,即按钮面板。
因此,actionPerformed方法必须判断点击了哪个按钮。
EventObject类是所有事宜类的超类,个中的getSource方法可以给出每个事宜的事宜源。事宜源是产生事宜和通知布告监听器的工具。
Object source = event.getSource( );
然后,actionPerformed方法可以检讨哪个按钮是事宜源:
if (source == yellowButton) . . .
else if (source == blueButton) . . .
else if (source == redButton) . . .
当然,这种办法须要包含按钮的面板拥有一个保存按钮引用的实例域。
可以看到,将按钮面板转换为动作监听器并不比定义内部类随意马虎。当面板包含多个用户界面元素时,会变得格外混乱。
警告:有些程序员采取其余一种办法在多个事宜源共享的监听器工具中找失事宜源。
ActionEvent类有一个getActionCommand方法,它将返回与这个动作有关的命令字符串。对付按钮,产生的默认命令字符串是按钮标签。如果采取这种办法,在actionPerformed方法中该当包含下列代码:
String command = event.getActionCommand( );
if (command.equals("Yellow")) . . . ;
else if (command.equals("Blue")) . . . ;
else if (command.equals("Red")) . . . ;
我们建议不要利用这种办法。依据按钮字符串存在着危险。很随意马虎犯这类缺点:
有一个按钮的标签为"Gray",但在检测时拼写的字符串却有一点差别:
if (command.equals("Grey")) . . .
当须要将运用程序国际化时,按钮字符串会带来很多烦恼。例如,要想利用德国版的按钮标签“Gelb”、“Blau”和“Rot”,就必须在修正按钮标签的同时,还要修正actionPerformed方法中的字符串。
java.util.EventObject 1.1
• Object getSource( )
返回发生事宜的工具引用。
java.awt.event.ActionEvent 1.1
• String getActionCommand( )
返回与这个动作事宜干系的命令字符串。如果动作事宜来源于按钮,命令字符串就即是按钮标签,除非已经利用setActionCommand方法对字符串进行了修正。
java.beans.EventHandler 1.4
• static Object create(Class listenerInterface, Object target, String action)
• static Object create(Class listenerInterface, Object target, String action, String eventProperty)
• static Object create(Class listenerInterface, Object target, String action, String eventProperty, String listenerMethod)
布局实现给定接口的代理类工具。无论是命名方法,还是接口的所有方法都将实行目标工具上的给定动作。
动作可以是一个方法名或目标的属性。如果是属性,实行它的设置方法。例如,动作"text"将变为调用setText方法。
事宜属性由一个或多个用逗号分隔的属性名组成。第一个属性从监听器方法的参数中读出。
第二个属性由结果工具读出等等。末了的结果将作为动作的参数。例如,属性"source.text"将变为调用getSource和getText方法。
实例:改变不雅观感
在默认情形下,Swing程序利用Metal不雅观感,可以采取两种办法改变不雅观感。第一种办法是在Java安装的子目录jre/lib下有一个文件swing.properties。在这个文件中,将属性swing.defaultlaf设置为所希望的不雅观感类名。例如,
swing.defaultlaf = com.sun.java.swing.plaf.motif.MotifLookAndFeel
把稳,Metal不雅观感位于javax.swing包中。其他的不雅观感包位于com.sun.java包中,并且不是在每个Java实现中都供应。现在,鉴于版权的缘故原由,Windows和Mac的不雅观感包只与Windows和Mac版本的Java运行时环境一起发布。
提示:下面给出一个对测试很有帮助的建议。由于属性文件中以#字符开始的行被忽略,以是,可以在swing.properties文件中供应几种不雅观感选择,并通过增删#字符来切换选择:
#swing.defaultlaf = javax.swing.plaf.metal.MetalLookAndFeelswing.defaultlaf = com.sun.java.swing.plaf.motif.MotifLookAndFeel#swing.defaultlaf = com.sun.java.swing.plaf.windows.WindowsLookAndFeel
采取这种办法开启不雅观感时必须重新启动程序。Swing程序只在启动时读取一次swing.properties文件。
第二种办法是动态地改变不雅观感。这须要调用静态的UIManager.setLookAndFeel方法,并供应所想要的不雅观感类名,然后再调用静态方法SwingUtilities.updateComponentTreeUI来刷新全部的组件集。这里须要向这个方法供应一个组件,并由此找到其他的所有组件。当UIManager.setLookAndFeel方法没有找到所希望的不雅观感或在加载过程中涌现缺点时,将会抛出非常。与前面一样,建议暂且将非常处理的代码跳过,等到第11章详细地讲述非常时就会理解了。
下面是一个例子,它显示了如何在程序中切换到Motif不雅观感:
String plaf = "com.sun.java.swing.plaf.motif.MotifLookAndFeel";try{UIMananger.setLookAndFeel(plaf);SwingUtilities.updateComponentTreeUI(panel);catch(Exception e) {e.printStackTrace( );}
为了列举安装的所有不雅观感实现,可以调用:
UIManager.LookAndFeelInfo[ ] infos = UIManager.getInstalledLookAndFeels( );
然后采取下列办法得到每一种不雅观感的名字和类名:
String name = infos[i].getName( );
String className = infos[i].getClassName( );
例8-2是一个完全的程序,它演示了如何切换不雅观感(如图8-3所示)的办法。这个程序与例8-1十分相似。我们遵照前一节的建议,利用赞助方法makeButton和匿名内部类指定按钮动作,即切换不雅观感。
在这个程序中,还有一点须要把稳的地方。在内部动作监听器类的actionPerformed方法中,须要将一个外部PlafPanel类的this引用通报给updateComponentTreeUI方法。回忆一下第6章所说过的,外部工具的this指针必须将外部类名作为前缀:
SwingUtilities.updateComponentTreeUI(PlafPanel.this);
例8-2 PlafTest.java
javax.swing.UIManager 1.2
• static UIManager.LookAndFeelInfo[ ] getInstalledLookAndFeels( )
得到一个用于描述已安装的不雅观感实现的工具数组。
• static setLookAndFeel(String className)
设置当前的不雅观感。
参数:className 不雅观感实现类的名称
javax.swing.UIManager.LookAndFeelInfo 1.2
• String getName( )
返回不雅观感的显示名称。
• String getClassName( )
返回不雅观感实现类的名称。
实例:捕获窗口事宜
并不是所有的事宜处理都像按钮点击那样大略。下面这个例子就有点繁芜,在第7章中我们曾经简要的先容过。在JDK 1.3中EXIT_ON_CLOSE选项涌现之前,当关闭主框架的时候,程序员必须手工地退出程序。在正规的程序中,每每希望用户在确认没有丢失所做事情之后再关闭程序。
例如,当用户关闭框架时,可能希望弹出一个对话框来警告用户没有保存的事情有可能会丢失,只有在用户确认之后才退出程序。
当程序用户试图关闭一个框架窗口时,JFrame工具便是WindowEvent的事宜源。在WindowListener接口中包含7个方法。当发生窗口事宜时,框架将调用这些方法来相应7个不同的事宜。它们的名字都是自阐明的,唯一的例外是在Windows下,常日将“iconified”称为“minimized”。下面是完全的WindowListener接口:
把稳:为了能够查看窗口是否被最大化,须要安装WindowStateListener。有关更加详细的信息请参阅后面的API注释。
正像前面曾经说过的那样,在Java中,实现一个接口的任何类都必须实现个中的所有方法;在这里,意味着须要实现7个方法。然而我们只对个中的名为windowClosing的方法感兴趣。
当然,可以这样定义实现这个接口的类:在windowClosing方法中增加一个对System.exit(0) 的调用,其他6个方法什么也不做:
适配器类
书写6个没有任何操作的方法代码显然是一种乏味的事情。出于简化的目的,每个含有多个方法的AWT监听器接口都配有一个适配器(adapter)类,这个类实现了接口中的所有方法,但每个方法没有做任何事情。例如,WindowAdapter类有7个没有做任何事情的方法。这意味着适配器类自动地知足了Java实现干系监听器接口的技能需求。可以通过扩展适配器类来指定对某些事宜的相应动作,而不必实现接口中的每个方法。(ActionListener这样的接口只有一个方法,因此没必要供应适配器类。)
下面利用窗口适配器。首先定义一个WindowAdapter类的扩展类,个中包含继续的6个没有做任何事情的方法和一个覆盖的方法windowClosing:
现在,可以将一个Terminator类型的工具注册为事宜监听器:
只要框架产生了窗口事宜,就会通过调用7个方法之中的一个方法将事宜通报给listener工具(如图8-4所示),个中6个方法没有做任何事情;windowClosing方法调用System.exit(0)终止运用程序的实行。
警告:如果在扩展适配器类时将方法名拼写错了,编译器不会捕捉到这个缺点。例如,如果在WindowAdapter中定义一个windowIsClosing方法,就会得到一个拥有8个方法的类,并且windowClosing方法没有做任何事情。
创建一个扩展于WindowAdapter的监听器类是一种很好的改进,但是还可以连续改进。事实上,没有必要为listener工具命名。只需写成:frame.addWindowListener(new Terminator( ));
不要就此止步!
我们可以将监听器类定义为框架的匿名内部类。
这段代码具有下列浸染:
• 定义了一个扩展于WindowAdapter类的无名类。
• 将windowClosing方法添加到匿名类中(与前面一样,这个方法将退出程序)。
• 从WindowAdapter继续6个没有做任何事情的方法。
• 创建这个类的一个工具,这个工具没有名字。
• 将这个工具通报给addWindowListener方法。
这里再次解释一下,利用匿名内部类的语法须要人们适应一段韶光,但得到的是更加简炼的代码。
java.awt.event.WindowListener 1.1
• void windowOpened(WindowEvent e)
窗口打开后调用这个方法。
• void windowClosing(WindowEvent e)
在用户发出窗口管理器命令关闭窗口时调用这个方法。须要把稳一点,仅当调用hide或
dispose方法后窗口才能够关闭。
• void windowClosed(WindowEvent e)
窗口关闭后调用这个方法。
• void windowIconified(WindowEvent e)
窗口图标化后调用这个方法。
• void windowDeiconified(WindowEvent e)
窗口非图标化后调用这个方法。
• void windowActivated(WindowEvent e)
激活窗口后调用这个方法。只有框架或对话框可以被激活。常日,窗口管理器会对活动窗
口进行润色,比如,高亮度标题栏。
• void windowDeactivated(WindowEvent e)
窗口变为未激活状态后调用这个方法。
java.awt.event.WindowStateListener 1.4
• void windowStateChanged(WindowEvent event)
窗口被极大化、图标化或规复为正常大小时调用这个方法。
java.awt.event.WindowEvent 1.1
• int getNewState( ) 1.4
• int getOldState( ) 1.4
返回窗口状态改变事宜中窗口的新、旧状态。返回的整型数值是下列数值之一:
Frame.NORMAL
Frame.ICONIFIED
Frame.MAXIMIZED_HORIZ
Frame.MAXIMIZED_VERT
Frame.MAXIMIZED_BOTH
以为文章不错的话,可以转发关注小编一下!!
!
来日诰日给大家讲述AWT事宜继续层次、AWT的语义事宜和低级事宜这一技能点~~~~~~~~~~