Swing包提供了一种非常实用的机制来封装命令,并将它们连接到多个事件源,这就是Action接口。一个动作是一个封装下列内容的对象:

× 命令的说明(一个文本字符串和一个可选图标);

× 执行命令所需要的参数(例如,在列举的例子中请求改变的颜色)。

Action接口包含下列内容:

[java] view plaincopy print?
  1. public void actionPerformed(ActionEvent e);
  2. public void setEnabled(boolean b);
  3. public boolean isEnabled();
  4. public void putValue(String key, Object value);
  5. public Object getValue(String key);
  6. public void addPropertyChangeListener(PropertyChangeListener listener);
  7. public void removePropertyChangeListener(PropertyChangeListener listener);

actionPerformed方法是ActionListener接口中的一个:实际上,Action接口扩展于ActionListener接口,因此,可以在任何需要ActionListener对象的地方使用Action对象。

setEnabled和isEnbaled两个方法允许启用或禁用这个动作,并检查这个动作当前是否启用。当一个连接到菜单或工具栏上的动作被禁用时,这个选项就会变成灰色。

putValue和getValue两个方法允许存储和检索动作对象中的任意名/值。有两个重要的预定义字符串:Action.NAME和Action.SMALL_ICON,用于将动作的名字和图标存储到一个动作对象中:

[java] view plaincopy print?
  1. action.putValue(Action.NAME,"Blue");
  2. action.putValue(Action.SMALL_ICON,new ImageIcon("blue-ball.gif"));

表1给出了所有预定义的动作表名称。

表1 预定义动作表名称
名称
NAME 动作名称,显示在按钮和菜单上
SMALL_ICON 存储小图标的地方;显示在按钮、菜单项或工具栏中
SHORT_DESCRIPTION 图标的简要说明;显示在工具提示中
LONG_DESCRIPTION 图标的详细说明;使用在在线帮助中。没有Swing组件使用这个值
MNEMONIC_KEY 快捷键缩写;显示在菜单项中
ACCELERATOR_KEY 存储加速击键的地方;Swing组件不使用这个值
ACTION_COMMAND_KEY 历史遗留;仅在旧版本的registerKeyboardAction方法中使用
DEFALUT 常用的综合属性;Swing组件不使用这个值

如果动作对象添加到菜单或工具栏上,它的名称和图标就会被自动地提取出来,并显示在菜单项或工具栏项中。SHORT_DESCRIPTION值变成了工具提示。

addPropertyChangeListener和removePropertyChangeListener两个方法能够让其他对象在动作对象的属性发生变化时得到通告,尤其是菜单或工具栏触发的动作。例如,如果增加一个菜单,作为动作对象的属性变更监听器,而这个动作对象爱你个随后被禁用,菜单就会被调用,并将动作名称变为灰色。属性变更监听器是一种常用的构造形式,它是JavaBeans组件模型的一部分。

需要注意,Action是一个接口,而不是一个类。实现这个接口的所有类都必须实现刚才讨论的7个方法。庆幸的是,有一个类实现了这个接口除actionPerformed方法之外的所有方法,它就是AbstractAction。这个类存储了所有名/值对,并管理着属性变更监听器。我们可以直接扩展AbstractAction类,并在扩展类中实现actionPerformed方法。

下面构造一个用于执行改变颜色命令的动作对象。首先存储这个命令的名称、图标和需要的颜色。将颜色存储在AbstractAction类提供的名/值对表中。下面是ColorAction类的代码。构造器设置名/值对,而actionPerformed方法执行改变颜色的动作。

[java] view plaincopy print?
  1. public class ColorAction extends AbstractAction
  2. {
  3. public ColorAction(String name,Icon icon,Color c)
  4. {
  5. putValue(Action.NAME,name);
  6. putValue(Action.SMALL_ICON,icon);
  7. putValue(Action.SHORT_DESCRIPTION,"Set panel color to "+name.toLowerCase());
  8. putValue("color",c);
  9. }
  10. public void actionPerformed(ActionEvent event)
  11. {
  12. Color c = (Color)getValue("color");
  13. buttonPanel.setBackground(c);
  14. }
  15. }

在测试程序中,创建了三个这个类的对象,如下所示:

[java] view plaincopy print?
  1. Action yellowAction = new ColorAction("Yellow",new ImageIcon("yellow-ball.gif"),Color.YELLOW);
  2. Action blueAction = new ColorAction("Blue",new ImageIcon("blue-ball.gif"),Color.BLUE);
  3. Action redAction = new ColorAction("Red",new ImageIcon("red-ball.gif"),Color.RED);

接下来,将这个动作与一个按钮关联起来。由于JButton有一个用Action对象作为参数的构造器,所以实现这项操作很容易。

[java] view plaincopy print?
  1. buttonPanel.add(new JButton(yellowAction));
  2. buttonPanel.add(new JButton(blueAction));
  3. buttonPanel.add(new JButton(redAction));

构造器读取动作的名称和图标,为工具提示设置简要说明,将动作设置为监听器。

最后,想要将这个动作对象添加到击键中,以便让用户敲击键盘命令来执行这项动作。为了将动作与击键关联起来,首先需要生成KeyStroke类对象。这是一个很有用的类,它封装了对键的说明。要想生成一个KeyStroke对象,不要调用构造器,而是调用KeyStroke类中的静态getKeyStroke方法:

[java] view plaincopy print?
  1. KeyStroke ctrlBKey = KeyStroke.getKeyStroke("ctrol B");

为了能够理解下一个步骤,需要知道Keyborad focus的概念。用户界面中可以包含许多按钮、菜单、滚动栏以及其他的组件。当用户敲击键盘时,这个动作会被发送给拥有焦点的组件。通常具有焦点的组件可以明显地察觉到(但并不总是这样),例如,在Java观感中,具有焦点的按钮在按钮文本周围有一个细的矩形边框。用户可以使用TAB键在组件之间移动焦点。当按下SPACE键时,就点击了拥有焦点的按钮。还有一些键执行一些其他的动作,例如,按下箭头键可以移动滚动条。

然而,在这里的示例中,并不希望将击键发送给拥有焦点的组件。否则,每个按钮都需要知道如何处理CTRL+Y、CTRL+B和CTRL+R这些组合键。

这是一个常见的问题,Swing设计者给出了一种很便捷的解决方案。每个JComponent有三个输入映射(input maps),每一个映射的KeyStroke对象都与动作关联。三个输入映射对应着三个不同的条件。

表2 输入映射条件
标志 激活条件
WHEN_FOCUSED 当这个组件拥有键盘焦点时
WHEN_ANCESTOR_OF_FOCUSED_COMPONENT 当这个组件包含了拥有键盘焦点的组件时
WHEN_IN_FOCUSED_WINDOW 当这个组件被包含在一个拥有键盘焦点组件的窗口中时

击键处理将按照下列顺序检查这些映射:

1)检查具有输入焦点组件的WHEN_FOCUSED映射。如果这个击键存在,将执行对应的动作。如果动作已启用,则停止处理。

2)从具有输入焦点的组件开始,检查其父组件的WHEN_ANCESTOR_OF_FOCUSED_COMPONENT映射。一旦找到击键对应的映射,就执行对应的动作。如果动作已启用,将停止处理。

3)查看具有输入焦点的窗口中的所有可视的和启用的组件,这个击键被注册到WHEN_IN_FOCUSED_WINDOW映射中。给这些组件(按照击键注册的顺序)一个执行对应动作的机会。一旦第一个启用的动作被执行,就停止处理。如果一个击键在多个WHEN_IN_FOCUSED_WINDOW映射中出现,这部分处理就可能会出现问题。

可以使用getInputMap方法从组件中得到输入映射。例如:

[java] view plaincopy print?
  1. InputMap imap = buttonPanel.getInputMap(JComponent.WHEN_FOCUSED);

WHEN_FOCUSED条件意味着在当前组件拥有键盘焦点时会查看这个映射。在这里的示例中,并不想使用这个映射。是某个按钮拥有输入焦点,而不是面板。其他的两个映射都能够很好地完成增加颜色改变击键的任务。在示例程序中使用的是WHEN_ANCESTOR_OF_FOCUSED_COMPONENT。

InputMap不能直接地将KeyStroke对象映射到Action对象。而是先映射到任意对象上,然后由ActionMap类实现将对象映射到动作上的第2个映射。这样很容易实现来自不同输入映射的击键共享一个动作的目地。

因而,每个组件都可以有三个输入映射和一个动作映射。为了将它们组合起来,需要为动作命名。下面是将键与动作关联起来的方式:

[java] view plaincopy print?
  1. imap.put(KeyStroke.getKeyStroke("ctrl Y"), "panel.yellow");
  2. ActionMap amap = buttonPanel.getActionMap();
  3. amap.put("panel.yellow",yellowAction);

习惯上,使用字符串none表示空动作。这样可以轻松地取消一个键动作:

[java] view plaincopy print?
  1. imap.put(KeyStroke.getKeyStroke("ctrl C"),"none");

警告:JDK文档提倡使用动作名作为动作键。我们并不认为这是一个好建议。在按钮和菜单项上显示的动作名,UI设计者可以随心所欲地进行更改,也可以将其翻译成多种语言。使用这种不牢靠的字符串作为查询键不是一种好的选择。建议将动作名与现实的名字分开。

下面总结一下用同一个动作响应按钮、菜单项或击键的方式:

1)实现一个扩展于AbstractAction类的类。多个相关的动作可以使用同一个类。

2)构造一个动作类的对象。

3)使用动作对象创建按钮或菜单项。构造器将从动作对象中读取标签文本和图标。

4)为了能够通过击键触发动作,必须额外地执行几步操作。首先定位顶层窗口组件,例如,包含所有其他组件的面板。

5)然后,得到顶层组件的WHEN_ANCESTOR_OF_FOCUS_COMPONENT输入映射。为需要的击键创建一个KeyStrike对象。创建一个描述动作字符串这样的动作键对象。将(击键、动作键)对添加到输入映射中。

6)最后,得到顶层组件的动作映射。将(动作键,动作对象)添加到映射中。

将按钮和击键映射到动作对象的完整程序代码如下:

[java] view plaincopy print?
  1. import java.awt.*;
  2. import java.awt.event.*;
  3. import javax.swing.*;
  4. public class ActionTest {
  5. public static void main(String[] args) {
  6. EventQueue.invokeLater(new Runnable() {
  7. public void run() {
  8. ActionFrame frame = new ActionFrame();
  9. frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  10. frame.setVisible(true);
  11. }
  12. });
  13. }
  14. }
  15. class ActionFrame extends JFrame {
  16. public ActionFrame() {
  17. setTitle("ActionTest");
  18. setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
  19. buttonPanel = new JPanel();
  20. // define actions
  21. Action yellowAction = new ColorAction("Yellow", new ImageIcon("yellow-ball.gif"), Color.YELLOW);
  22. Action blueAction = new ColorAction("Blue", new ImageIcon("blue-ball.gif"), Color.BLUE);
  23. Action redAction = new ColorAction("Red", new ImageIcon("red-ball.gif"), Color.RED);
  24. // add buttons for these actions
  25. buttonPanel.add(new JButton(yellowAction));
  26. buttonPanel.add(new JButton(blueAction));
  27. buttonPanel.add(new JButton(redAction));
  28. // add panel to frame
  29. add(buttonPanel);
  30. // associate the Y, B, and R keys with names
  31. InputMap imap = buttonPanel.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
  32. imap.put(KeyStroke.getKeyStroke("ctrl Y"), "panel.yellow");
  33. imap.put(KeyStroke.getKeyStroke("ctrl B"), "panel.blue");
  34. imap.put(KeyStroke.getKeyStroke("ctrl R"), "panel.red");
  35. // associate the names with actions
  36. ActionMap amap = buttonPanel.getActionMap();
  37. amap.put("panel.yellow", yellowAction);
  38. amap.put("panel.blue", blueAction);
  39. amap.put("panel.red", redAction);
  40. }
  41. public class ColorAction extends AbstractAction {
  42. public ColorAction(String name, Icon icon, Color c) {
  43. putValue(Action.NAME, name);
  44. putValue(Action.SMALL_ICON, icon);
  45. putValue(Action.SHORT_DESCRIPTION, "Set panel color to " + name.toLowerCase());
  46. putValue("color", c);
  47. }
  48. public void actionPerformed(ActionEvent event) {
  49. Color c = (Color) getValue("color");
  50. buttonPanel.setBackground(c);
  51. }
  52. }
  53. private JPanel buttonPanel;
  54. public static final int DEFAULT_WIDTH = 300;
  55. public static final int DEFAULT_HEIGHT = 200;
  56. }

结果显示:

转载于:https://www.cnblogs.com/jiangzhaowei/p/7448735.html

Java Swing Action 动作相关推荐

  1. JAVA Swing 事件监听

    EventListner 接口 它是一个标记接口,每一个监听器接口扩展.这个类定义在java.util包. 类声明 以下是声明java.util.EventListener接口: public int ...

  2. java swing action_Swing ActionListener接口

    处理ActionEvent的类应该实现此接口.该类的对象必须在组件中注册.可以使用addActionListener()方法注册该对象.当动作事件发生时,将调用该对象的actionPerformed方 ...

  3. java swing开发窗体程序开发(三)事件(Mouse,Foucs,Key,Window)

    接着刚刚的事件讲 补充一点:事件的触发前提,添加了这个监听器的组件必须是处于激活状态的才可行 (一)MouseEvent事件 该事件的触发是由鼠标的动作引起的,引起的情况可以是下面5种,按下鼠标,释放 ...

  4. java swing原理浅析

    2019独角兽企业重金招聘Python工程师标准>>> 没有接触过ui编程的人在学习ui编程时可能会对ui组件和各组件间的关系有点混乱,下面笔者就java swing的原理做下简单分 ...

  5. java swing 链接_JAVA中Jtable标签设置超级链接:基于Java Swing的超链接标签和超链接按钮的实现...

    希望在一个标签上设置超级链接,找到了如下的一种方法: 1.要解决的问题 基于Java Swing的超链接实现 2.自定义一个超链接标签控件[LinkLabel] 2.1.完整代码如下: public ...

  6. java swing刷新_Swing界面刷新问题(转)

    在Java Swing编程中,往往会遇到需要动态刷新界面的时候,例如动态刷新JLabel的文本,JTextField里的文本等等.但是往往却没有达到我们预期的效果,我相信很多朋友都遇到过本文将要说的这 ...

  7. Atitit。DD dragdrop拖拽功能c#.net java swing的对比与实现总结

    Atitit.D&D drag&drop拖拽功能c#.net java swing的对比与实现总结 1. 实现一个D&D操作一般包括三个步骤: 1 2. .net黑头的拖曳机制 ...

  8. java swing事件机制_java SWing事件调用的两种机制

    /** * java swing中事件调用的两种机制: * (一)响应机制 * (二)回调机制 */ package test; import java.awt.*; import java.awt. ...

  9. 小demo, java swing窗口编程(JDK 1.6)

    //这段代码主要是创建一个登录窗口界面,在这个界面中有文本组件.普通按钮组件.标签组件,它们是按照网格组布局管理方式布局, import javax.swing.*;import java.awt.* ...

  10. java情人节_情人节写给女朋友Java Swing代码程序

    马上又要到情人节了,再不解风情的人也得向女友表示表示.作为一个程序员,示爱的时候自然也要用我们自己的方式. 这里给大家上传一段我在今年情人节的时候写给女朋友的一段简单的Java Swing代码,主要定 ...

最新文章

  1. SQL2005学习(九),将数据库备份到网络共享文件夹中
  2. matplotlib里的fig和ax的区别。
  3. BC:带你温习并解读《中国区块链技术和应用发展白皮书》—区块链技术发展路线图
  4. 工业用微型计算机(27)-dos和BIOS调用(1)
  5. java堆排序解决topk问题,详解堆排序解决TopK问题
  6. 终于升级?89年的Linux内核C语言“跟上时代”转成现代C
  7. 【转】关于微信开发者平台移动应用获取签名解决问题
  8. ERROR: Failed to Setup IP tables: Unable to enable SKIP DNAT rule
  9. 牛逼!SpringBoot+Vue企业级支付系统!附源码!
  10. IDEA下配置安卓环境
  11. matlab图例只显示文字不显示线条
  12. linux系统支持速达软件吗,速达3000系列常见问题100问
  13. 砌体的弹性模量计算_3.2 砌体的计算指标
  14. 【PHP学习】Yii2框架Gii模块使用
  15. 什么是核函数?如何理解?
  16. 马克思 第四章 资本主义的形成及其本质
  17. Python | 爬虫抓取智联招聘(基础版)
  18. 误删了php文件怎么恢复,【问题】phpstorm误删文件后,恢复成了0KB
  19. Android 下拉控件Spinner
  20. win 7 桌面快捷键分类

热门文章

  1. 《数据结构与算法 C语言版》—— 2.2线性表的顺序表示与实现
  2. 西安Uber优步司机奖励政策(1月11日~1月17日)
  3. 9, Java NIO SocketChannel
  4. The Python Debugger Command
  5. 解决ubuntu的firefox上网速度慢[转]
  6. 坑爹的RegExp test()
  7. 2021 年 4 月程序员工资统计,这太可怕了……
  8. 阿里巴巴技术总监全解中台架构
  9. 余额宝技术架构及演进
  10. IBM推出世界最小电脑,应用区块链技术防偷骗!