[转载]Merlin 的魔力: AWT 摘要

Merlin 的魔力: AWT 摘要


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();
}
}


blue_rule.gif
c.gif
c.gif
u_bold.gif回页首


工具箱 insets

在上一个专栏中,我提到了 用 setExtendedState() 最大化 Frame 的功能。如果您将框架的状态设置为 Frame.MAXIMIZED_BOTH ,您的框架就被完全最大化了。但如果您不希望把框架最大化,却希望它的大小填满用户的桌面区域(扣除所有桌面装饰的大小),那么现在您可以查询那些装饰使用的 Insets (请参阅清单 2)。这些信息由 Toolkit 的 getScreenInsets() 方法提供。如果从屏幕大小中减去那些 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() 方法中。


blue_rule.gif
c.gif
c.gif
u_bold.gif回页首


颜色常量大写

Java 语言规范的第 6.8 节包含包、方法、字段和常量等项的命名约定。关于常量名的子节(6.8.5)声明常量不应使用小写字母,但从一开始, Color 类中的全部颜色常量如 red 、 green 和 blue 就是以全小写指定的。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 方法现在已被修改为以小写字母开头。


blue_rule.gif
c.gif
c.gif
u_bold.gif回页首


检测鼠标滚轮移动

自从上个世纪以来 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);
}


blue_rule.gif
c.gif
c.gif
u_bold.gif回页首


输入事件

这最后一个功能比您刚开始想象的要多一些,因为测试程序只使用了已添加的功能的一小部分。基本上,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);
}


blue_rule.gif
c.gif
c.gif
u_bold.gif回页首


完整的示例

清单 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();
}
}

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/374079/viewspace-130265/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/374079/viewspace-130265/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值