【IT168 技术文章】J2SE 版本 1.4 中新增了一项有趣的 Swing 功能。Swing 控件现在可以提供听觉反馈来对特定事件作出响应,不过缺省情况下这项功能是禁用的。J2SE 版本 1.4 中新增了一项有趣的 Swing 功能。Swing 控件现在可以提供听觉反馈来对特定事件作出响应,不过缺省情况下这项功能是禁用的。新增的这项功能有助于 Swing 控件更好地模仿系统本地操作系统的控件的行为。
听觉基本知识
Swing 使用一种可插式外观和感觉(Pluggable Look-and-Feel,PLAF)体系结构。开发者不必针对不同组件为颜色和字体之类的设置进行硬编码;取而代之的是,组件将从用户界面管理器(User Interface(UI)Manager)请求这些设置。作为开发者,您可以告诉 UI 管理器要让用户看到什么样的界面;您可以选择 Windows、Motif 或 Metal 样式等。UI 管理器接下来就可以实际告诉每个组件应该如何显示它自身。对于象按钮这样的组件来说,前景颜色是通过设置 Button.foreground 属性来控制的,如下所示:
2
在这里, Button.foreground 为用户界面属性名,而 Color.red 代表特定的设置。改变了设置之后,所有新的按钮的前景颜色都将是红色。(也有方法可以改变以前创建的按钮的前景颜色。)虽然不同的预置外观和感觉为这些设置提供了缺省值,您还是可以重设它们。
在 J2SE 1.4 下,您可以用类似的方式来启用听觉反馈。您只要了解 UI 属性名和合适的设置就可以了。属性在这里被命名为 AuditoryCues.playList ,设置则为听觉提示名称的一个 String 数组。UI 管理器接下来将把这些名称映射到特定操作发生时将播放的声音文件。
下面将给出系统提供的外观和感觉中所支持的声音列表。它们的名称本身就颇具解释性。
CheckBoxMenuItem.commandSound
InternalFrame.closeSound
InternalFrame.maximizeSound
InternalFrame.minimizeSound
InternalFrame.restoreDownSound
InternalFrame.restoreUpSound
MenuItem.commandSound
OptionPane.errorSound
OptionPane.informationSound
OptionPane.questionSound
OptionPane.warningSound
PopupMenu.popupSound
RadioButtonMenuItem.commandSound
提供给 AuditoryCues.playList 属性的 String 名称数组就是这样 ― 一个事件 名称的集合。UI 管理器负责将这些名称映射到特定于外观和感觉的声音。
您可以从这些名称中手动地创建一个真正希望支持的事件名称的数组,不过这并不是必需的。值得庆幸的是,对于常用的组来说已经有两个系统定义过的设置可以使用,还有一个设置可以用于 Metal 外观和感觉。
这些设置提供了一个查找键 AuditoryCues.allAuditoryCues ,它允许您从 UI 管理器查找适用于所有声音的数组。一旦您查找了这个数组,就可以用 AuditoryCues.playList 键将其存储在 UI 管理器中,如下所示:
2 UIManager.get("AuditoryCues.allAuditoryCues"));
3
您还可以使用另外两个查找键: AuditoryCues.noAuditoryCues ,即无声,还有 AuditoryCues.defaultCueList ,它只为四种 OptionPane 设置播放声音提示,专门用于 Metal 外观和感觉。
一旦您改变了 AuditoryCues.playList 设置,就可以使用一组新的声音提示了。当特定操作发生时,UI 管理器将检查播放列表,寻找与该操作关联的键。UI 管理器接下来将使用这个键来查找要载入并播放的声音文件。如果提示(cue)数组中不存在任何键,就不会播放任何声音。
如果您不喜欢某个声音,可以通过将其提示名映射到另一个文件来替换它。举例来说,在下面的代码中,您将看到“问题(question)”声音被映射到系统提供的“错误(error)”声音文件:
这就是在 Swing 程序中播放与预先定义好的操作关联的听觉提示所涉及的所有内容。
完整示例
为了展示我们刚才描述过的功能,清单 1 中的程序将显示三个单选按钮,让您选择希望使用三种提示设置中的哪一种。您可以参看图 1 中简单的用户界面。
图 1. 示例应用程序界面

程序还显示了两个显示弹出窗口的按钮。启用后,显示弹出窗口的操作将触发声音提示。请您自己将确认对话框出现时播放“ 错误”声音文件的代码行标记出来。
清单 1. 声音示例
2 import java.awt.event.*;
3 import javax.swing.*;
4 public class Audio extends JFrame {
5
6 public Audio() {
7 super("Auditory Popups");
8 setDefaultCloseOperation(EXIT_ON_CLOSE);
9 UIManager.put("AuditoryCues.playList",
10 UIManager.get("AuditoryCues.defaultCueList"));
11 UIManager.put("OptionPane.questionSound",
12 "sounds/OptionPaneError.wav");
13 JPanel contentPane = (JPanel)this.getContentPane();
14 JPanel center = new JPanel();
15 ButtonGroup buttonGroup = new ButtonGroup();
16 JRadioButton defaultAudio = new JRadioButton("Default", true);
17 center.add(defaultAudio);
18 buttonGroup.add(defaultAudio);
19 defaultAudio.addActionListener(new ActionListener() {
20 public void actionPerformed(ActionEvent e) {
21 UIManager.put("AuditoryCues.playList",
22 UIManager.get("AuditoryCues.defaultCueList"));
23 }
24 });
25 JRadioButton offAudio = new JRadioButton("Off", false);
26 center.add(offAudio);
27 buttonGroup.add(offAudio);
28 offAudio.addActionListener(new ActionListener() {
29 public void actionPerformed(ActionEvent e) {
30 UIManager.put("AuditoryCues.playList",
31 UIManager.get("AuditoryCues.noAuditoryCues"));
32 }
33 });
34 JRadioButton onAudio = new JRadioButton("On", false);
35 center.add(onAudio);
36 buttonGroup.add(onAudio);
37 onAudio.addActionListener(new ActionListener() {
38 public void actionPerformed(ActionEvent e) {
39 UIManager.put("AuditoryCues.playList",
40 UIManager.get("AuditoryCues.allAuditoryCues"));
41 }
42 });
43 contentPane.add(center, BorderLayout.CENTER);
44 JButton confirmButton = new JButton("Confirmation Dialog");
45 contentPane.add(confirmButton, BorderLayout.SOUTH);
46 confirmButton.addActionListener(new ActionListener() {
47 public void actionPerformed(ActionEvent e) {
48 int result = JOptionPane.showConfirmDialog(Audio.this,
49 "Confirm?");
50 if (result == JOptionPane.YES_OPTION) {
51 JOptionPane.showMessageDialog(Audio.this, "Confirmed");
52 } else {
53 JOptionPane.showMessageDialog(Audio.this, "Rejected");
54 }
55 }
56 });
57 JButton messageButton = new JButton("Message Dialog");
58 contentPane.add(messageButton, BorderLayout.NORTH);
59 messageButton.addActionListener(new ActionListener() {
60 public void actionPerformed(ActionEvent e) {
61 JOptionPane.showMessageDialog(Audio.this, "The Message");
62 }
63 });
64 this.pack();
65 show();
66 }
67 public static void main(String args[]) {
68 new Audio();
69 }
70 }
71