IBM®
跳转到主要内容
    中国 [选择]    使用条款
 
 
Select a scope: Search for:    
    首页    产品    服务与解决方案     支持与下载    个性化服务    
跳转到主要内容

developerWorks 中国  >  Java technology  >

Merlin 的魔力: AWT 摘要

在尺寸设定、颜色、鼠标滚轮和输入事件上的更改明细

developerWorks
文档选项

未显示需要 JavaScript 的文档选项


级别: 初级

John Zukowski (jaz@zukowski.net), 总裁, JZ Ventures 公司

2001 年 11 月 01 日

Merlin 为 AWT 库添加了几种功能,包括查明屏幕装饰如桌面工具栏所占用空间的功能、将“颜色”常量变成大写,鼠标滚轮支持以及更好地区分鼠标和键盘键以及键的位置的功能。请跟着 John Zukowski 学习,他描述了这些更改并提供了深入的详细信息,以便您快速入门。请在 “客户端 Java 编程”讨论论坛与作者和其他读者交流您关于本文的心得。

“抽象窗口工具箱”(Abstract Window Toolkit(AWT))已随着新的 Merlin 发行版的出现而升级。许多更改都不是太大,但其优点已足够重要,值得一提。在这个月,我们将看一下下面 4 种新功能:

  • 查明屏幕装饰所占用空间的功能。
  • Color 类中的常量变为大写。
  • 支持响应鼠标滚轮事件。
  • 更好地区分鼠标按钮、小键盘键和 shift 键的功能。

开始

为演示新的 AWT 功能,我们将创建一个程序将屏幕设为全屏(最小化桌面装饰如工具栏)并使用新的颜色常量设置背景。您将能够通过旋转鼠标滚轮或使用左和右 shift 键更改背景色。

清单 1 提供了该程序的基本骨架程序。遗憾的是,在要使用的鼠标滚轮支持功能中仍存在错误(有关详细信息请参阅 参考资料)。为使这种功能起作用,您需要把 JButton 添加到 JScrollPane ,再把 JScrollPane 添加到框架中。这个错误使得这个骨架程序比必需的复杂了一点。

清单 1. 创建可关闭框架的骨架程序
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class AwtTest {
  // See bug 4475240
  static JButton button = new JButton();
  static JScrollPane pane = new JScrollPane(button);
  public static void main(String args[]) {
    JFrame frame = new JFrame("AwtTest");
    // See bug 4475240
    frame.getContentPane().add(button, BorderLayout.CENTER);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.show();
  }
}





回页首


工具箱 insets

在上一个专栏中,我提到了 setExtendedState() 最大化 Frame 的功能。如果您将框架的状态设置为 Frame.MAXIMIZED_BOTH ,您的框架就被完全最大化了。但如果您不希望把框架最大化,却希望它的大小填满用户的桌面区域(扣除所有桌面装饰的大小),那么现在您可以查询那些装饰使用的 Insets (请参阅清单 2)。这些信息由 ToolkitgetScreenInsets() 方法提供。如果从屏幕大小中减去那些 insets,您就得到了窗口的应有大小。为正确地定位,您还需要使用顶端和左边的 insets。

清单 2. 确定屏幕大小
  private static void sizeScreen(JFrame frame) {
    Toolkit kit = Toolkit.getDefaultToolkit();
    Dimension screenSize = kit.getScreenSize();
    GraphicsConfiguration config = frame.getGraphicsConfiguration();
    Insets insets = kit.getScreenInsets(config);
    screenSize.width -= (insets.left + insets.right);
    screenSize.height -= (insets.top + insets.bottom);
    frame.setSize(screenSize);
    frame.setLocation(insets.left, insets.top);
  }

只需把 sizeScreen() 调用添加到 main() 方法中。





回页首


颜色常量大写

Java 语言规范的第 6.8 节包含包、方法、字段和常量等项的命名约定。关于常量名的子节(6.8.5)声明常量不应使用小写字母,但从一开始, Color 类中的全部颜色常量如 redgreenblue 就是以全小写指定的。Merlin 也直接开了个先例,现在以全大写提供相同的常量。现在尚不反对使用旧名称,但在您的 1.4 程序中您可以使用较新的名称。

我们将为测试程序创建一个颜色常量数组和一个对这些颜色常量进行循环的计数程序,然后提供一个 changeBackground() 方法,该方法按两个方向的其中一个方向对这些颜色常量进行循环(请参阅“清单 3”)。

清单 3. 更改背景色
  private static final Color colors[] = {
    Color.BLACK,
    Color.BLUE,
    Color.CYAN,
    Color.DARK_GRAY,
    Color.GRAY,
    Color.GREEN,
    Color.LIGHT_GRAY,
    Color.MAGENTA,
    Color.ORANGE,
    Color.PINK,
    Color.RED,
    Color.WHITE,
    Color.YELLOW
  };
  static int colorCounter;
  
  private static final int UP = 1;
  private static final int DOWN = 2;
  private static void changeBackground(JFrame frame, int direction) {
    // See bug 4475240
    // w/o bug, change background of getContentPane()
    button.setBackground(colors[colorCounter]);
    // Update counter based on direction
    if (direction == UP) {
      colorCounter++;
    } else {
      --colorCounter;
    }
    // Wrap colors
    if (colorCounter == colors.length) {
      colorCounter = 0;
    } else if (colorCounter < 0) {
      colorCounter = colors.length-1;
    }
  }

向您的 main() 例程添加对 changeBackground() 方法的调用。

在其它类如 GridBagLayout 中也对命名约定进行了更新, GridBagLayout 类包括几个 protected 方法如 AdjustForGravity() ,这些 protected 方法现在已被修改为以小写字母开头。





回页首


检测鼠标滚轮移动

自从上个世纪以来 Java 开发者就嚷着要求的一个功能是支持鼠标滚轮旋转事件。随着 Merlin 发行版的出现,现在您可以为任何 Component 增加一个 MouseWheelListener 并做出相应的响应。除了前面提及的错误之外,它运行得很顺利。 JScrollPane 组件甚至随预注册的侦听器一起提供,所以当这个组件获得焦点且用户移动鼠标滚轮时窗格将会滚动。

该侦听器有一个方法, mouseWheelMoved() ,它获取一个 MouseWheelEvent 参数。在事件中,您可以使用 getScrollAmount() 查明滚动总量,使用 getScrollType() 查明是单元滚动还是块滚动、使用 getWheelRotation 查明滚动方向和鼠标滚轮旋转的次数,为方便起见,还可以使用 getUnitsToScroll() 查明要滚动的单元。

在测试程序中,我们增加了一个鼠标滚轮侦听器,它让背景色按照某一方向在颜色数组中循环,如清单 4 所示。文档声明鼠标滚轮事件向上传递容器层次结构,但错误导致这件事无法发生,所以您需要为按钮增加一个侦听器。确保在 main() 方法中添加一个侦听器。

清单 4. 增加鼠标滚轮侦听器
  private static void attachMouseWheelListener(final JFrame frame) {
    MouseWheelListener listener = new MouseWheelListener() {
      public void mouseWheelMoved(MouseWheelEvent e) {
        int count = e.getWheelRotation();
        int direction = (Math.abs(count) > 0) ? UP : DOWN;
        changeBackground(frame, direction);
      }
    };
    button.addMouseWheelListener(listener);
  }





回页首


输入事件

这最后一个功能比您刚开始想象的要多一些,因为测试程序只使用了已添加的功能的一小部分。基本上,Merlin 添加了区别同一键的不同版本(键区键和常规键)以及键盘键和鼠标按钮的不同次序的功能。例如,以前无法说出按下 shift 再单击和单击不同按钮之间的不同;两者产生相同的鼠标事件。有了 InputEvent 类中下列新常量的帮助,一切都不同了:

  • ALT_DOWN_MASK
  • CTRL_DOWN_MASK
  • META_DOWN_MASK
  • SHIFT_DOWN_MASK
  • BUTTON1_DOWN_MASK
  • BUTTON2_DOWN_MASK
  • BUTTON3_DOWN_MASK
  • BUTTON1_CHANGED_MASK
  • BUTTON2_CHANGED_MASK
  • BUTTON3_CHANGED_MASK

如果您想找出按下的是哪个按钮,下列方法更常用:

  • isButton1Down()
  • isButton2Down()
  • isButton3Down()

MouseEvent 还提供 getButton() 方法用来发现哪个按钮改变了状态。

所有这些方法和常量应该会使得对按钮事件做出响应更加容易。

区分同一个键的不同版本要求对 KeyEvent 类做一些修改。您可以使用 getKeyLocation() 从事件中得到键的位置;您会重新使用下列常量之一:

  • KEY_LOCATION_LEFT
  • KEY_LOCATION_NUMPAD
  • KEY_LOCATION_RIGHT
  • KEY_LOCATION_STANDARD
  • KEY_LOCATION_UNKNOWN

通过询问键的位置,您可以区分小键盘键、标准键以及左和右 shift 键。

对于测试程序,我们只简单地让键侦听器根据按下的是左还是右 shift 键按向上或向下的方向循环,如清单 5 所示。我们务必要首先核实按下的是哪个键,然后再检查其位置。当然,还要在 main() 方法中添加对例程的调用。

清单 5. 增加键侦听器
  private static void attachKeyListener(final JFrame frame) {
    KeyListener listener = new KeyAdapter() {
      public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_SHIFT) {
          int location = e.getKeyLocation();
          int direction = (location == KeyEvent.KEY_LOCATION_LEFT) ? 
            UP : DOWN;
          changeBackground(frame, direction);
        }
      }
    };
    button.addKeyListener(listener);
  }





回页首


完整的示例

清单 6 为您提供了一个完整的示例来试验所有这些新功能。修正鼠标滚轮侦听器后,您将可以不用按钮和滚动窗格。

清单 6 完整的示例
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class AwtTest {
  private static final Color colors[] = {
    Color.BLACK,
    Color.BLUE,
    Color.CYAN,
    Color.DARK_GRAY,
    Color.GRAY,
    Color.GREEN,
    Color.LIGHT_GRAY,
    Color.MAGENTA,
    Color.ORANGE,
    Color.PINK,
    Color.RED,
    Color.WHITE,
    Color.YELLOW
  };
  static int colorCounter;
  private static final int UP = 1;
  private static final int DOWN = 2;
  // See bug 4475240
  static JButton button = new JButton();
  static JScrollPane pane = new JScrollPane(button);
  private static void sizeScreen(JFrame frame) {
    Toolkit kit = Toolkit.getDefaultToolkit();
    Dimension screenSize = kit.getScreenSize();
    GraphicsConfiguration config = frame.getGraphicsConfiguration();
    Insets insets = kit.getScreenInsets(config);
    screenSize.width -= (insets.left + insets.right);
    screenSize.height -= (insets.top + insets.bottom);
    frame.setSize(screenSize);
    frame.setLocation(insets.left, insets.top);
  }
  private static void changeBackground(JFrame frame, int direction) {
    // See bug 4475240
    // w/o bug, change background of getContentPane()
    button.setBackground(colors[colorCounter]);
    // Update counter based on direction
    if (direction == UP) {
      colorCounter++;
    } else {
      --colorCounter;
    }
    // Wrap colors
    if (colorCounter == colors.length) {
      colorCounter = 0;
    } else if (colorCounter < 0) {
      colorCounter = colors.length-1;
    }
  }
  private static void attachMouseWheelListener(final JFrame frame) {
    MouseWheelListener listener = new MouseWheelListener() {
      public void mouseWheelMoved(MouseWheelEvent e) {
        int count = e.getWheelRotation();
        int direction = (Math.abs(count) > 0) ? UP : DOWN;
        changeBackground(frame, direction);
      }
    };
    // See bug 4475240
    // w/o bug, add to frame
    button.addMouseWheelListener(listener);
  }
  private static void attachKeyListener(final JFrame frame) {
    KeyListener listener = new KeyAdapter() {
      public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_SHIFT) {
          int location = e.getKeyLocation();
          int direction = (location == KeyEvent.KEY_LOCATION_LEFT) ? 
            UP : DOWN;
          changeBackground(frame, direction);
        }
      }
    };
    // See bug 4475240
    // w/o bug, add to frame
    button.addKeyListener(listener);
  }
  public static void main(String args[]) {
    JFrame frame = new JFrame("AwtTest");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    // See bug 4475240
    frame.getContentPane().add(button, BorderLayout.CENTER);
    sizeScreen(frame);
    changeBackground(frame, UP);
    attachMouseWheelListener(frame);
    attachKeyListener(frame);
    frame.show();
  }
}



参考资料



关于作者

John Zukowski

John Zukowski 通过 JZ Ventures 公司从事战略性 Java 咨询,同时还担任一些 jGuru的由社区推动的 Java 常见问题解答的常驻指导。他最近的著作有 Apress 出版的 Java Collections Definitive Guide to Swing for Java 2 (第 2 版)。您可以通过 jaz@zukowski.net与 John 联系。




对本文的评价










回页首


IBM 公司保留在 developerWorks 网站上发表的内容的著作权。未经IBM公司或原始作者的书面明确许可,请勿转载。如果您希望转载,请通过 提交转载请求表单 联系我们的编辑团队。
    关于 IBM 隐私条约 联系 IBM 使用条款