本文曾发表于天极网:http://dev.yesky.com/185/2690685.shtml
Java SE 6之GUI:让界面更加绚丽(下)
Java是一种非常强大的编程语言,但Java的GUI能力一直是它的软肋。虽然Java提供2种图形解决方案,AWT和Swing。但这2种图形库的功能十分有限,使用它们并不能带来更多的用户体验。而且AWT和Swing的更新速度很慢。一直到Java SE 5也没什么明显的变化。幸好Java SE 6终于为它们增加大更强大的功能。有了这些功能,使用AWT和Swing设计的用户界面可以更贴近用户。为了使读者能够更早地体验Java SE 6 GUI的美丽,本文就Java SE 6 GUI提供的主要功能进行讨论。
一、显示启动界面
现在很多商业和非商业软件在启动时都必须初始化,有时初始化的时间会很长,如photoshop、flash等,为了让用户有耐心继续等待,不要误以为死器了,这些软件在初始化之前总是显示一个图形界面来告诉用户软件正在做什么。如图1是Flash8在启动时的初始化界面。
图1 Flash8的启动界面
当我们在设计软件时可能也需要这样一个界面。当然,这在Java SE的早期版本中也可以做到,但比较费劲,基本的实现是将一个图形放到窗体上,然后先显示这个,这需要编写一定的代码,而Java SE 6提供了一个更简单的方法,可以不添加一行代码,而且在界面要改变时还不需要重新编译源程序。让我们先看一个简单的例子。
import java.awt.*;
public class TestSplash
{
public static void main(String args[])
{
try
{
// 为了让启动界面多显示3秒,
// 如果是正常的程序,这里应该时初始化代码
Thread.sleep(3000);
JFrame frame = new JFrame("Java SE 6 启动界面演示");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel label = new JLabel("我的标签", JLabel.CENTER);
frame.add(label, BorderLayout.CENTER);
frame.setSize(300, 95);
frame.setVisible(true);
}
catch (InterruptedException e)
{
}
}
}
上面的程序是一个非常简单的界面演示程序,它的界面如图2所示。
图2
如果使用java TestSplash直接运行上面的程序,将立刻显示如图2的界面。Java SE 6在java命令上提供了一个选项,可以在显示程序主界面之前先显示一幅图。
java –splash:splash.gif TestSplash
如果运行以上的命令,在出现图2所示的界面之前会先显示splash.gif,然后再过几秒钟splash.gif自动关闭,然后会显示主界面。在上面程序中的Thread.sleep(3000); 是为了使splash.gif显示的时间长一些,可以将这句改为直正的初始化代码。splash.gif文件如图3所示。
图3 splash.gif
在发布时一般将程序所用到的.class文件打包成一个或几个.jar文件,如果是这样,可以将splash.gif一同打包在.jar文件中。然后在manifest.mf文件中使用SplashScreen-Image指定启动界面图象。
在打包之前,先建一个文本文件manifest.mf,内容如下
Manifest-Version: 1.0
Main-Class: TestSplash
SplashScreen-Image: splash.gif
然后通过以下命令进行打包
jar -mcvf manifest.mf Splash.jar TestSplash.class splash.gif
然后通过如下命令运行程序
java -jar Splash.jar
现在我们已经可以显示一个启动界面了,但这只是一幅静态的图,而在大多数时还需要在这幅图上显示一些信息,如正在初始化什么。在Java SE 6也提供了可以操作这幅图的功能。下面的代码演示了如何操作启动界面。
import java.awt.*;
public class TestSplash
{
public static void main(String args[])
{
try
{
String[] info = new String[]
{ "正在初始化API", "正在初始化网络", "正在初始化数据库" };
SplashScreen splash = SplashScreen.getSplashScreen();
Graphics g = splash.createGraphics();
if (splash != null)
{
for (int i = 0; i < 3; i++)
{
g.setColor(Color.BLACK);
g.drawString(info[i], 350, 170 + i * 15);
splash.update();
Thread.sleep((i + 1)*1000);
}
}
JFrame frame = new JFrame("Java SE 6 启动界面演示");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel label = new JLabel("我的标签", JLabel.CENTER);
frame.add(label, BorderLayout.CENTER);
frame.setSize(300, 95);
frame.setVisible(true);
}
catch (Exception e)
{
}
}
}
上面的代码SplashSreen获得启动界面,然后再通过createGraphics得到一个图形句柄。本例将在启动界面显示按一定时间间隔显示三个字符串,这三个字符串保存在info数组中。启动界面如图4所示。
图4 在启动界面上显示三个字符串
另外需要提一点,在SplashScreen类中有一个close方法用于关闭启动界面,但这个方法一般不需要调用,因为在主窗口显示时这个方法自动被调用。当然,要想在初始化过程中关闭这启动界面,如发生初始化错误后,就不能再往下初始化了,因此,就要关闭这个界面,然后或退出程序,或直接进入主界面。
二、系统托盘
现在有很多程序除了提供了一个完整的主界面外,在它最小化或者启动后在右下角的系统托盘区总是有一个小图标,如金山词霸、QQ和MSN等。图5显示了一台计算机的系统托盘里的图标。
图5 系统托盘
如果使用C++、Delphi(Pascal)等语言实现这个功能非常简单,只要调用一下系统API即可,但在以前版本(Java SE 5以前)的Java SE中Sun并未提供访问系统托盘的类,在那时使用Java访问系统托盘的唯一方法就是使用JNI直接调用系统API,但这种方法实现比较复杂,而且如果这样做,就破坏了Java的跨平台特性(除非你为每一个操作系统平台都做一个这样的类)。Java的这个缺陷缓和终于在Java SE 6中得到弥补。在java.awt包中提供了一个SystemTray类可以直接访问系统托盘。下面的代码演示了一个简单的实现。
import java.awt.*;
public class MyTray
{
public static void main(String args[])
{
// 判断当前操作系统是否支持系统托盘
// 最好加上这个判断,否则这个程序可能在其它操作系统上无法正常工作
if (SystemTray.isSupported())
{
// 通过静态方法getSystemTray()得到系统托盘
SystemTray tray = SystemTray.getSystemTray();
// 装载托盘图象
Image image = Toolkit.getDefaultToolkit().getImage(
"tray.gif");
// 为这个托盘加一个弹出菜单
PopupMenu popup = new PopupMenu();
MenuItem item = new MenuItem("我的菜单");
popup.add(item);
// 为这个托盘加一个提示信息
TrayIcon trayIcon = new TrayIcon(image, "提示信息", popup);
try
{
tray.add(trayIcon);
}
catch (AWTException e)
{
System.err.println("无法向这个托盘添加新项: " + e);
}
}
else
{
System.err.println("无法使用系统托盘!");
}
}
}
在运行上面的程序之前,tray.gif一定要放到当前目录,如果放到其它的目录,要在程序中指明。图6是程序运行结果。最左侧的五彩光盘图标就是本程序加入了。
图6 运行结果
如果多次调用tray.add(trayIcon),可以在一个程序中向系统托盘添加多个图标。但要注意,图象可以使用一个Image对象,但弹出菜单要为每一个图标建一个,如果不建,就设为null。如:
TrayIcon trayIcon1 = new TrayIcon(image, "提示信息1", null);
TrayIcon trayIcon2 = new TrayIcon(image, "提示信息2", null);
TrayIcon trayIcon3 = new TrayIcon(image, "提示信息3", null);
tray.add(trayIcon1);
tray.add(trayIcon2);
tray.add(trayIcon3);
图7为显示界面图
图7
Java SE 6还为我们提供了3种提示信息,它们是警告、错误和信息。如使用如下语句添加提示信息。
添加警告提示
trayIcon.displayMessage("警告", "这是一个警告提示!", TrayIcon.MessageType.WARNING);
图8 警告提示
添加错误提示
trayIcon.displayMessage("错误", "这是一个错误提示!", TrayIcon.MessageType.ERROR);
图9 错误提示
添加信息提示
trayIcon.displayMessage("信息", "这是一个信息提示!", TrayIcon.MessageType.INFO);
图10 信息提示
交互对话框
在一般的程序语言或开发工具中都有一些标准的对话框以方便和用户交互,如Delphi中有InputBox对话框用来采集用户的输入信息。在Java SE 6中也提供了类似的标准对话框来满足这些需求。
在Java SE 6中提供了一种输入对话框,下面是一个使用这个对话框的简单例子。
JOptionPane pane = new JOptionPane("文本", JOptionPane.INFORMATION_MESSAGE);
pane.setWantsInput(true);
JDialog dialog = pane.createDialog(parent, "请输入文本");
dialog.setModalityType(Dialog.ModalityType.APPLICATION_MODAL);
dialog.setVisible(true);
String msg = pane.getInputValue();
上面的代码使用JoptionPane对象的createDialog方法来建立一个输入对话框。上面的代码有几点需要注意一下。
1. 如果将pane.setWantsInput(true)改为pane.setWantsInput(false),那么输入对话框将消失。
2. 这个对话框使用的是APPLICATION_MODAL模式,Java SE 6还提供了一个DOCUMENT_MODAL模式,这两种模式最大的区别是第一种模式是对整个应用程序的,也就是说,使用这种模式弹出对话框后,整个程序都不访问,而使用第二种模式,只有弹出对话框的窗体不可访问,其它的窗体并不受影响。图11为以上代码的程序界面。
图11
图象转换
Java在图象处理上是比较强大的,但是以前的Java SE版本对于GIF图只能读,不能写。这并不是因为技术原因,而是因为GIF专利的原因。但最近这个专利到期了,因此,在Java SE 6中提供了读写GIF的功能。下面的代码演示了如何通过Java来将其它格式的图象转换为gif格式。
import java.io.*;
import java.awt.image.*;
import java.util.*;
public class ToGIF
{
public static void main(String args[]) throws IOException
{
// 可以将abc.bmp换成其它格式的图象
File inputFile = new File(“abc.bmp”);
BufferedImage input = ImageIO.read(inputFile);
File outputFile = new File("abc.gif");
ImageIO.write(input, "GIF", outputFile);
}
}
如果你想知道在Java SE 6支持什么图象格式,可以使用如下语句进行查看。
System.out.println(Arrays.toString(ImageIO.getWriterFormatNames()));
显示结果
[BMP, bmp, jpg, JPG, wbmp, jpeg, png, PNG, JPEG, WBMP, GIF, gif]
国内最棒的Google Android技术社区(eoeandroid),欢迎访问!
《银河系列原创教程》发布
《Java Web开发速学宝典》出版,欢迎定购