经常听朋友说,java编写的程序界面比较单一,不好进行个性化配置。现在让我们一起来了解有关java界面样式相关类的知识,以及如何用java写出变幻莫测的用户界面,让java程序也拥有时髦的换肤功能。
实现原理
java平台成熟后,设计人员与开发人员就认识到需要连续性好、兼容性好、容易使用的java程序界面。这时sun就推出了“look and feel”机制迎合这种需求。它提供了一种独特的、与平台无关的程序外观,以及标准的界面行为。它可以在各个平台上使用同一“look and feel”,从而缩短设计与开发周期,降低软件使用人员的培训费用。这是“look and feel”设计的初衷。现在我们来使用这种特性为java程序穿上花衣。
要让java程序具备换肤功能,首先要求有以下jdk版本:
1.sun jdk1.1.7b/swing1.1.1 (windows);
2.sun jdk1.2.2 (windows、solaris、 linux);
3.sun jdk 1.3 或以上版本 (windows)。
我们先来熟悉“look and feel”几个相关的类以及api,以便来理解我们的换肤术。与“look and feel”密切相关的是lookandfeel抽象类和uimanager类。
lookandfeel类
lookandfeel是一个抽象类,除了提供了一些static方法,还定义了一些抽象的个性化设置方法来由子类实现。
从jdk1.1.3开始,sun提供了三个lookandfeel的子类 javax.swing.plaf.metal.metallookandfeel、com.sun.java.swing.plaf.motif.motiflookandfeel、com.sun.java.swing.plaf.windows. windowslookandfeel。它们分别提供了“metal”、“motif”与“windows”的界面式样。也就是说,任何基于swing的界面程序本身都可以使用三种系统提供的皮肤。实际上我们也可以直接或间接继承lookandfeel类,自己编写一种“皮肤”。在这里我们要使用到一个开放源代码的产品skin look and feel 1.2.2,在http://www.l2fprod.com/可以找到它的全部源代码。skin look and feel本身还可以更换http://www.l2fprod.com/提供的各种“皮肤”,让你的程序可以各种“皮肤”示人。
uimanager类
这个类就是swing界面管理的核心,管理swing的小应用程序以及应用程序样式的状态。uimanager类提供了下列静态方法用于更换与管理“look and feel”:
static void addauxiliarylookandfeel(lookandfeel laf)
//增加一个“look and feel”到辅助的“look and feels”列表
static lookandfeel[] getauxiliarylookandfeels()
//返回辅助的“look and feels”列表(可能为空)。
static string getcrossplatformlookandfeelclassname()
//返回缺省的实现了跨平台的look and feel――即java look and feel(jlf)。
static uimanager.lookandfeelinfo[] getinstalledlookandfeels()
//返回了在目前已经安装的lookandfeel的信息。
static lookandfeel getlookandfeel()
//返回当前使用的look and feel
static string getsystemlookandfeelclassname()
//返回与当前系统相关的本地系统look and feel,如果没有实现本地look and
feel则返回缺省的跨平台的look and feel。
static void installlookandfeel(string name, string classname)
//创建一个新的look and feel并安装到当前系统。
static void installlookandfeel(uimanager.lookandfeelinfo info)
//创建一个新的look and feel并安装到当前系统。
static boolean removeauxiliarylookandfeel(lookandfeel laf)
//从辅助的“look and feels”列表删除一个“look and feel”
static void setinstalledlookandfeels(uimanager.lookandfeelinfo[] infos)
//设置当前的已安装look and feel信。
static void setlookandfeel(lookandfeel newlookandfeel)
//设置当前使用的lookandfeel。
static void setlookandfeel(string classname)
//设置当前使用的lookandfeel。参数是类名。
源码剖析
下面的源代码可以在skin look and feel 1.2.2下的源代码根目录下找到(比如我下载的zip包是skinlf-1.2.2-20020611.zip,解压后,在src目录下的skinit.java)。
public class skinit extends javax.swing.japplet
{
/**
* the main program for the skinit class
*
* @param args the command line arguments
* @exception exception description of exception
*/
public static void main(string[] args) throws exception
{
if (args.length == 0) {
printusage();
}
int mainclassnameindex = -1;
string gtktheme = null;
string kdetheme = null;
string packtheme = null;
for (int i = 0, c = args.length; i < c; i++) {
if (args[i].equals("-gtk")) {
gtktheme = args[++i];
}
else if (args[i].equals("-kde")) {
kdetheme = args[++i];
}
else if (args[i].equals("-pack")) {
packtheme = args[++i];
}
else {
mainclassnameindex = i;
break;
}
}
string[] realargs = new string[args.length - mainclassnameindex - 1];
for (int i = 0, c = realargs.length; i < c; i++) {
realargs[i] = args[mainclassnameindex + i + 1];
}
// first try to find the class
class clazz = null;
try {
clazz = class.forname(args[mainclassnameindex]);
} catch (classnotfoundexception e) {
system.err.println("the class " + args[mainclassnameindex] + "
was not found in the classpath.");
system.exit(1);
} catch (throwable e) {
e.printstacktrace();
system.exit(1);
}
// if the class exists, get the main method
method mainmethod = null;
try {
mainmethod = clazz.getmethod("main", new class[]{string[].class});
} catch (nosuchmethodexception e) {
system.err.println("no method public static void main(string[] args) in " +
clazz.getname());
system.exit(1);
} catch (throwable e) {
e.printstacktrace();
system.exit(1);
}
// try to make sure the main method is accessible
try {
mainmethod.setaccessible(true);
} catch (throwable e) {
}
// main class and main method found, time to load the skin
skin skin = null;
if (packtheme != null) {
if (skinutils.debug) {
system.out.println("loading themepack " + packtheme);
}
skin = skinlookandfeel.loadthemepack(packtheme);
}
else if (gtktheme != null) {
if (kdetheme != null) {
skin = new compoundskin(skinlookandfeel.loadskin(gtktheme),
skinlookandfeel.loadskin(kdetheme));
}
else {
skin = skinlookandfeel.loadskin(gtktheme);
}
}
/*
* try to use the user default skin
*/
if (skin == null) {
if (skinutils.debug) {
system.out.println("trying user skin");
}
skin = skinlookandfeel.getskin();
}
if (skin != null) {
skinlookandfeel.setskin(skin);
skinlookandfeel lnf = new skinlookandfeel();
uimanager.setlookandfeel(lnf);
uimanager.addpropertychangelistener(
new propertychangelistener() {
public void propertychange(propertychangeevent event) {
object newlf = event.getnewvalue();
if ((newlf instanceof skinlookandfeel) == false) {
try {
uimanager.setlookandfeel(new skinlookandfeel());
} catch (exception e) {
e.printstacktrace();
}
}
}
});
}
else {
system.out.println("no gtk theme provided, defaulting to application look and
feel");
}
try {
mainmethod.invoke(null, new object[]{realargs});
} catch (illegalaccessexception e) {
system.err.println("please make sure the class " + clazz.getname() +
" and the method main(string[] args) are public.");
system.exit(1);
} catch (throwable e) {
e.printstacktrace();
system.exit(1);
}
}
/**
* description of the method
*/
static void printusage() {
string usage = "skinit - skin look and feel wrapper/n" +
"usage: skinit [options] class [args...]/n" +
"
闽公网安备 35060202000074号