如何设置外观
Swing 的体系结构经过设计,因此您可以更改应用程序 GUI 的“外观”(L&F)(请参阅Swing 体系结构概述)。 “外观”是指 GUI 小部件的外观(更正式地为JComponents
),“感觉”是指小部件的行为方式。
Swing 的体系结构通过将每个组件分为两个不同的类来实现多个 L&F:JComponent
子类和相应的ComponentUI
子类。例如,每个JList
实例都有ListUI
的具体实现(ListUI
扩展了ComponentUI
)。 ComponentUI
子类在 Swing 的文档中由各种名称引用-“ UI”,“组件 UI”,“ UI 委托”和“外观委托”均用于标识ComponentUI
子类。
大多数开发人员永远不需要直接与 UI 委托进行交互。在大多数情况下,JComponent
子类在内部使用 UI 委托以实现关键功能,而JComponent
子类提供的掩盖方法用于对 UI 委托的所有访问。例如,JComponent
子类中的所有绘画都委托给 UI 委托。通过委托绘画,“外观”可以根据 L&F 的不同而不同。
每个 L&F 都有责任为 Swing 定义的每个ComponentUI
子类提供具体的实现。例如,Java 外观创建MetalTabbedPaneUI
的实例,以提供JTabbedPane
的 L&F。 UI 委托的实际创建由 Swing 为您处理-在大多数情况下,您无需直接与 UI 委托进行交互。
本节的其余部分讨论以下主题:
可用的外观
Sun 的 JRE 提供以下 L&F:
-
CrossPlatformLookAndFeel
—这是在所有平台上看起来都相同的“ Java L&F”(也称为“金属”)。它是 Java API(javax.swing.plaf.metal
)的一部分,并且是默认设置,如果您在代码中不执行任何操作来设置其他 L&F,将使用该默认设置。 -
SystemLookAndFeel
-在这里,应用程序使用其运行系统固有的 L&F。系统 L&F 在运行时确定,其中应用程序要求系统返回适当 L&F 的名称。 -
合成器-使用 XML 文件创建自己的外观的基础。
-
复用-一种将 UI 方法委派给多个不同外观实现的方式。
对于 Linux 和 Solaris,如果安装了 GTK 2.2 或更高版本,则系统 L&F 为“ GTK”,否则为“ Motif”。对于 Windows,系统 L&F 是“ Windows”,它模仿正在运行的特定 Windowsos(经典 Windows,XP 或 Vista)的 L&F。 GTK,Motif 和 Windows L&F 由 Sun 提供,并且随 Java SDK 和 JRE 一起提供,尽管它们不是 Java API 的一部分。
苹果提供了自己的 JVM,其中包括其专有的 L&F。
总而言之,当您使用SystemLookAndFeel
时,将看到以下内容:
Platform | 外观 |
---|---|
Solaris,Linux 和 GTK 2.2 或更高版本 | GTK+ |
其他 Solaris,Linux | Motif |
IBM UNIX | IBM* |
HP UX | HP* |
Classic Windows | Windows |
Windows XP | Windows XP |
Windows Vista | Windows Vista |
Macintosh | Macintosh* |
*由系统供应商提供。
您在 API 中看不到系统 L&F。 Java SDK 附带了所需的 GTK,Motif 和 Windows 软件包,它们是:
com.sun.java.swing.plaf.gtk.GTKLookAndFeel
com.sun.java.swing.plaf.motif.MotifLookAndFeel
com.sun.java.swing.plaf.windows.WindowsLookAndFeel
请注意,该路径包括java
,而不包括javax
。
Note:
GTK L&F 仅在安装了 GTK 2.2 或更高版本的 UNIX 或 Linux 系统上运行,而 Windows L&F 仅在 Windows 系统上运行。像 Java(金属)L&F 一样,Motif L&F 可以在任何平台上运行。
Sun 的所有 L&F 都有很多共性。此通用性在 API(javax.swing.plaf.basic
)的Basic
外观中定义。 Motif 和 Windows L&F 分别通过扩展javax.swing.plaf.basic
中的 UI 委托类来构建(可以通过执行相同的操作来构建自定义 L&F)。未经扩展,不得使用“基本” L&F。
在 API 中,您将看到四个 L&F 软件包:
-
javax.swing.plaf.basic
—创建自定义 L&F 时要扩展的基本 UI 委托 -
javax.swing.plaf.metal
— Java L&F,也称为 CrossPlatform L&F(“金属”是此 L&F 的 Sun 项目名称)。该 L&F 的当前默认“主题”(如下所述)为“海洋”,因此通常称为海洋 L&F。 -
javax.swing.plaf.multi
—一种多路复用的外观,它允许 UI 方法同时委派给多个外观实现。它可以用于增强特定外观的行为,例如,通过 L&F 在 Windows 外观之上提供音频提示的 L&F。这是创建残障人士可访问的外观的方式。 -
javax.swing.plaf.synth
—使用 XML 文件轻松配置的 L&F(在本类的下一部分中讨论)
您不仅限于 Java 平台随附的 L&F。您可以使用程序的 Classpath 中的任何 L&F。外部 L&F 通常在一个或多个 JAR 文件中提供,您可以在运行时将其添加到程序的 Classpath 中。例如:
java -classpath .;C:\java\lafdir\customlaf.jar YourSwingApplication
一旦外部 L&F 进入程序的 Classpath,您的程序就可以像使用 Java 平台附带的任何 L&F 一样使用它。
以编程方式设置外观
Note:
如果要设置 L&F,则应将其作为应用程序的第一步。否则,无论您请求什么 L&F,都有冒着初始化 Java L&F 的风险。当静态字段引用 Swing 类时,可能会无意中发生,这会导致 L&F 加载。如果尚未指定 L&F,则将加载 JRE 的默认 L&F。对于 Sun 的 JRE,默认值为 Java L&F,对于苹果的 JRE,默认值为 Apple L&F,依此类推。
Swing 组件使用的 L&F 通过javax.swing
包中的UIManager
类指定。每当创建 Swing 组件时,该组件都会向 UI管理 器询问实现该组件 L&F 的 UI 委托。例如,每个JLabel
构造函数都向 UI管理 器查询适合于标签的 UI 委托对象。然后,它使用该 UI 委托对象来实现其所有绘图和事件处理。
要以编程方式指定 L&F,请使用UIManager.setLookAndFeel()
方法,并将LookAndFeel
的适当子类的完全限定名称作为其参数。例如,以下代码段中的粗体代码使程序使用跨平台的 Java L&F:
public static void main(String[] args) {
try {
// Set cross-platform Java L&F (also called "Metal")
UIManager.setLookAndFeel(
UIManager.getCrossPlatformLookAndFeelClassName());
}
catch (UnsupportedLookAndFeelException e) {
// handle exception
}
catch (ClassNotFoundException e) {
// handle exception
}
catch (InstantiationException e) {
// handle exception
}
catch (IllegalAccessException e) {
// handle exception
}
new SwingApplication(); //Create and show the GUI.
}
或者,此代码使程序使用系统 L&F:
public static void main(String[] args) {
try {
// Set System L&F
UIManager.setLookAndFeel(
UIManager.getSystemLookAndFeelClassName());
}
catch (UnsupportedLookAndFeelException e) {
// handle exception
}
catch (ClassNotFoundException e) {
// handle exception
}
catch (InstantiationException e) {
// handle exception
}
catch (IllegalAccessException e) {
// handle exception
}
new SwingApplication(); //Create and show the GUI.
}
您还可以使用外观的实际类名作为UIManager.setLookAndFeel()
的参数。例如,
// Set cross-platform Java L&F (also called "Metal")
UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
or
// Set Motif L&F on any platform
UIManager.setLookAndFeel("com.sun.java.swing.plaf.motif.MotifLookAndFeel");
您不仅限于上述参数。您可以为程序的 Classpath 中的任何 L&F 指定名称。
指定外观:命令行
您可以使用-D
标志设置swing.defaultlaf
属性来在命令行中指定 L&F。例如:
java -Dswing.defaultlaf=com.sun.java.swing.plaf.gtk.GTKLookAndFeel MyApp
java -Dswing.defaultlaf=com.sun.java.swing.plaf.windows.WindowsLookAndFeel MyApp
指定外观:swing.properties 文件
指定当前 L&F 的另一种方法是使用swing.properties
文件设置swing.defaultlaf
属性。您可能需要创建此文件,该文件位于 Sun 的 Java 版本的lib
目录中(其他 Java 供应商可能使用其他位置)。例如,如果您在javaHomeDirectory\bin
中使用 Java 解释器,则swing.properties
文件(如果存在)在javaHomeDirectory\lib
中。这是一个swing.properties文件内容的示例:
# Swing properties
swing.defaultlaf=com.sun.java.swing.plaf.windows.WindowsLookAndFeel
UI管理 器如何选择外观
当 UI管理 器需要设置 L&F 时,以下是外观确定步骤:
-
如果程序在需要外观之前设置 L&F,则 UI管理 器将try创建指定外观类的实例。如果成功,则所有组件都将使用该 L&F。
-
如果程序尚未成功指定 L&F,则 UI管理 器将使用
swing.defaultlaf
属性指定的 L&F。如果在命令行的swing.properties
文件和中都指定了属性,则命令行定义优先。 -
如果这些步骤均未导致有效的 L&F,则 Sun 的 JRE 使用 Java L&F。其他供应商(例如 Apple)将使用其默认的 L&F。
启动后更改外观
即使程序的 GUI 可见,您也可以使用setLookAndFeel
更改 L&F。要使现有组件反映新的 L&F,请对每个顶级容器调用一次SwingUtilities
updateComponentTreeUI
方法。然后,您可能希望调整每个顶级容器的大小,以反映其包含的组件的新大小。例如:
UIManager.setLookAndFeel(lnfName);
SwingUtilities.updateComponentTreeUI(frame);
frame.pack();
An Example
在以下示例LookAndFeelDemo.java
中,您可以try使用不同的外观。该程序创建一个带有按钮和标签的简单 GUI。每次单击按钮,标签都会递增。
您可以通过更改第 18 行的LOOKANDFEEL
常量来更改 L&F。前几行的 注解 告诉您可接受的值:
// Specify the look and feel to use by defining the LOOKANDFEEL constant
// Valid values are: null (use the default), "Metal", "System", "Motif",
// and "GTK"
final static String LOOKANDFEEL = "Motif";
在这里,常量设置为“ Motif”,这是可以在任何平台上运行的 L&F(默认设置为“ Metal”)。 “ GTK”将不会在 Windows 上运行,“ Windows”将仅在 Windows 上运行。如果您选择的 L&F 无法运行,则将获得 Java 或 Metal,即 L&F。
在代码中实际设置 L&F 的部分中,您将看到设置它的几种不同方法,如上所述:
if (LOOKANDFEEL.equals("Metal")) {
lookAndFeel = UIManager.getCrossPlatformLookAndFeelClassName();
// an alternative way to set the Metal L&F is to replace the
// previous line with:
// lookAndFeel = "javax.swing.plaf.metal.MetalLookAndFeel";
您可以通过 注解/取消 注解 这两种选择来验证两个参数是否都起作用。
以下是LookAndFeelDemo源文件的列表:
package lookandfeel;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.plaf.metal.*;
public class LookAndFeelDemo implements ActionListener {
private static String labelPrefix = "Number of button clicks: ";
private int numClicks = 0;
final JLabel label = new JLabel(labelPrefix + "0 ");
// Specify the look and feel to use by defining the LOOKANDFEEL constant
// Valid values are: null (use the default), "Metal", "System", "Motif",
// and "GTK"
final static String LOOKANDFEEL = "Metal";
// If you choose the Metal L&F, you can also choose a theme.
// Specify the theme to use by defining the THEME constant
// Valid values are: "DefaultMetal", "Ocean", and "Test"
final static String THEME = "Test";
public Component createComponents() {
JButton button = new JButton("I'm a Swing button!");
button.setMnemonic(KeyEvent.VK_I);
button.addActionListener(this);
label.setLabelFor(button);
JPanel pane = new JPanel(new GridLayout(0, 1));
pane.add(button);
pane.add(label);
pane.setBorder(BorderFactory.createEmptyBorder(
30, //top
30, //left
10, //bottom
30) //right
);
return pane;
}
public void actionPerformed(ActionEvent e) {
numClicks++;
label.setText(labelPrefix + numClicks);
}
private static void initLookAndFeel() {
String lookAndFeel = null;
if (LOOKANDFEEL != null) {
if (LOOKANDFEEL.equals("Metal")) {
lookAndFeel = UIManager.getCrossPlatformLookAndFeelClassName();
// an alternative way to set the Metal L&F is to replace the
// previous line with:
// lookAndFeel = "javax.swing.plaf.metal.MetalLookAndFeel";
}
else if (LOOKANDFEEL.equals("System")) {
lookAndFeel = UIManager.getSystemLookAndFeelClassName();
}
else if (LOOKANDFEEL.equals("Motif")) {
lookAndFeel = "com.sun.java.swing.plaf.motif.MotifLookAndFeel";
}
else if (LOOKANDFEEL.equals("GTK")) {
lookAndFeel = "com.sun.java.swing.plaf.gtk.GTKLookAndFeel";
}
else {
System.err.println("Unexpected value of LOOKANDFEEL specified: "
+ LOOKANDFEEL);
lookAndFeel = UIManager.getCrossPlatformLookAndFeelClassName();
}
try {
UIManager.setLookAndFeel(lookAndFeel);
// If L&F = "Metal", set the theme
if (LOOKANDFEEL.equals("Metal")) {
if (THEME.equals("DefaultMetal"))
MetalLookAndFeel.setCurrentTheme(new DefaultMetalTheme());
else if (THEME.equals("Ocean"))
MetalLookAndFeel.setCurrentTheme(new OceanTheme());
else
MetalLookAndFeel.setCurrentTheme(new TestTheme());
UIManager.setLookAndFeel(new MetalLookAndFeel());
}
}
catch (ClassNotFoundException e) {
System.err.println("Couldn't find class for specified look and feel:"
+ lookAndFeel);
System.err.println("Did you include the L&F library in the class path?");
System.err.println("Using the default look and feel.");
}
catch (UnsupportedLookAndFeelException e) {
System.err.println("Can't use the specified look and feel ("
+ lookAndFeel
+ ") on this platform.");
System.err.println("Using the default look and feel.");
}
catch (Exception e) {
System.err.println("Couldn't get specified look and feel ("
+ lookAndFeel
+ "), for some reason.");
System.err.println("Using the default look and feel.");
e.printStackTrace();
}
}
}
private static void createAndShowGUI() {
//Set the look and feel.
initLookAndFeel();
//Make sure we have nice window decorations.
JFrame.setDefaultLookAndFeelDecorated(true);
//Create and set up the window.
JFrame frame = new JFrame("SwingApplication");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
LookAndFeelDemo app = new LookAndFeelDemo();
Component contents = app.createComponents();
frame.getContentPane().add(contents, BorderLayout.CENTER);
//Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
//Schedule a job for the event dispatch thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
Themes
引入主题是一种轻松更改跨平台 Java(金属)外观的颜色和字体的方式。在上面列出的示例程序LookAndfeelDemo.java
中,可以通过将第 23 行的THEME
常量设置为三个值之一来更改 Metal L&F 的主题:
-
DefaultMetal
-
Ocean
-
Test
自 Java SE 5 起,Ocean
比纯 Metal 外观要柔和一些,它一直是 Metal(Java)L&F 的默认主题,尽管它的名字是DefaultMetal
并不是 Metal 的默认主题(它在 Java SE 5 之前是,解释其名称)。 Test
主题是在TestTheme.java中定义的主题,您必须使用LookAndfeelDemo.java
进行编译。在编写时,TestTheme.java
设置了三种原色(结果有些奇怪)。您可以修改TestTheme.java
以测试您喜欢的任何颜色。
从LookAndfeelDemo.java
的第 92 行开始可以找到设置主题的代码部分。请注意,您必须使用 Metal L&F 设置主题。
if (LOOKANDFEEL.equals("Metal")) {
if (THEME.equals("DefaultMetal"))
MetalLookAndFeel.setCurrentTheme(new DefaultMetalTheme());
else if (THEME.equals("Ocean"))
MetalLookAndFeel.setCurrentTheme(new OceanTheme());
else
MetalLookAndFeel.setCurrentTheme(new TestTheme());
UIManager.setLookAndFeel(new MetalLookAndFeel());
}
SwingSet2 演示程序
当您下载JDK 和 JavaFX 演示和 samplesBinding 包并打开它时,会有一个demo\jfc
文件夹,其中包含一个名为SwingSet2
的演示程序。该程序具有图形丰富的 GUI,可让您从菜单中更改外观。此外,如果您使用的是 Java(金属)外观,则可以选择各种不同的主题。 SwingSet2\src
文件夹中包含各种主题的文件(例如RubyTheme.java
)。
这是“海洋”主题,这是跨平台 Java(金属)外观的默认设置:
这是“钢”主题,它是跨平台 Java(金属)外观的原始主题:
要在安装了 JDK 的系统上运行SwingSet2
演示程序,请使用以下命令:
java -jar SwingSet2.jar
这将为您提供默认的海洋主题。
要获取金属 L&F,请运行以下命令:
java -Dswing.metalTheme=steel -jar SwingSet2.jar