第5章 边框、图标和动作
本章介绍Swing的三种实用工具:边框、图标和动作。
边框绘制在组件的边界周围,它有许多不同的各类:线边框、雕刻边框、不光滑的边框等等。边框本身不是组件,所以,它们绘制在指定组件的边衬中。
图标是图形对象,通常是一个小图像。与边框一样,图标在指定组件的指定位置上绘制。
动作封装图形用户界面的一个逻辑操作,并且还简化用户界面元素的构造工作。动作通常由一个或多个图标或文本字符串组成。可以把动作添加到某些容器中,这些容器创建一个组件与这个动作相关联。例如,利用JMenu.add(Action)方法,可把动作添加到一个菜单中。当一个动作添加到一个菜单中时,这个菜单用与这个动作相关联的文本和图标来创建一个菜单项并把这个菜单项添加到菜单中。
边框、图标和动作都是很有意义的,因为它们都可以与多个组件相关联。由于边框和图标都不是组件,但却都能绘制到组件中,所以,可以在支持使用边框和图标的多个组件中共享边框和图标。动作也必须被多个组件所共享,并且用来作为控制的中心点以维护与这个动作相关联的组件的启用状态。
5.1 边框
通过构造所需类型的边框,然后把这个边框传送给JComponent.setBorder(Border),所有JComponent扩展(JViewport除外)都可以有边框。虽然每个组件可以只有一个边框,但Swing支持组合边框。因此,在实际应用中,单个组件可以使数个边框嵌套在一起,使边框有一定的深度。
边框的使用很简单。例如,图5-1示出了一个带标题边框的JPanel实例。
图5-1 一个带标题边框的JPanel实例
例5-1例出了图5-1所示的小应用程序的代码。
例5-1 一个带边框的JPanel的小应用程序
import java.awt.BorderLayout;
import javax.swing.*;
import javax.swing.border.*;
public class Test extends JApplet {
public void init() {
JPanel panel = new JPanel();
panel.setBorder(new TitledBorder("JPanel Border"));
getContentPane().add(panel, BorderLayout.CENTER);
}
}
这个小应用程序创建一个带标题的边框,这个边框传递给面板的setBorder方法。
5.1.1 边框和边衬
AWT容器有一个insets属性,它定义容器的边衬。布局管理器仔细地布局一个容器中的各个组件,以便这些组件不会侵占这个容器的边衬区。容器的insets属性是一个只读属性,修改AWT容器insets属性唯一的方法是子类化一个容器并重载它的getInsets方法。
5.1.2 Swing的边框类型
例5-2 显示所有Swing边框类型的小应用程序
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
public class Test extends JApplet {
public void init() {
JPanel jpanel = new AllBordersPanel();
getContentPane().add(jpanel, BorderLayout.CENTER);
}
}
class AllBordersPanel extends JPanel {
public AllBordersPanel() {
JPanel bl = new PanelWithTitle("Bevel Lowered"),
br = new PanelWithTitle("Bevel Raised"),
c = new PanelWithTitle("Compound"),
l = new PanelWithTitle("Line"),
m = new PanelWithTitle("Matte"),
e = new PanelWithEmptyBorder("Empty"),
t = new PanelWithTitle("Titled"),
sbr = new PanelWithTitle("Soft Bevel Raised"),
sbl = new PanelWithTitle("Soft Bevel Lowered"),
el = new PanelWithTitle("Etched Lowered"),
er = new PanelWithTitle("Etched Raised");
setLayout(new GridLayout(4,3,2,2));
ImageIcon icon = new ImageIcon(this.getClass().getResource("smiley.gif"));
Dimension iconsz = new Dimension(icon.getIconWidth(),
icon.getIconHeight());
bl.setBorder(BorderFactory.createLoweredBevelBorder());
br.setBorder(BorderFactory.createRaisedBevelBorder());
sbr.setBorder(new SoftBevelBorder(BevelBorder.RAISED));
sbl.setBorder(new SoftBevelBorder(BevelBorder.LOWERED));
t.setBorder(BorderFactory.createTitledBorder("Titled"));
l.setBorder(
BorderFactory.createLineBorder(Color.black,2));
c.setBorder(
BorderFactory.createCompoundBorder(
BorderFactory.createCompoundBorder(
BorderFactory.createLineBorder(Color.gray,10),
BorderFactory.createRaisedBevelBorder()),
BorderFactory.createCompoundBorder(
BorderFactory.createLineBorder(Color.blue,5),
BorderFactory.createLoweredBevelBorder())));
el.setBorder(BorderFactory.createEtchedBorder(
getBackground().brighter(),
getBackground().darker()));
er.setBorder(BorderFactory.createEtchedBorder(
getBackground().darker(),
getBackground().brighter()));
m.setBorder(BorderFactory.createMatteBorder(
iconsz.height, iconsz.width,
iconsz.height, iconsz.width,
icon));
add(br); add(bl); add(sbr);
add(sbl); add(c); add(el);
add(er); add(e); add(l);
add(m); add(t);
}
}
class PanelWithTitle extends JPanel {
private String title;
public PanelWithTitle(String title) {
this.title = title;
}
public void paintComponent(Graphics g) {
FontMetrics fm = g.getFontMetrics();
Dimension size = getSize();
int titleW = fm.stringWidth(title);
g.setColor(Color.black);
g.drawString(title, size.width/2 - titleW/2,
size.height/2);
}
}
class PanelWithEmptyBorder extends PanelWithTitle {
public PanelWithEmptyBorder(String title) {
super(title);
setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
}
public void paintComponent(Graphics g) {
Dimension size = getSize();
Insets insets = getInsets();
g.setColor(Color.red);
g.fillRect(insets.left,insets.top,
size.width-2*insets.left,
size.height-2*insets.top);
super.paintComponent(g);
}
}
5.1.3 不透明与透明之间的比较
例5-3 部分透明的边框的样例
import javax.swing.*;
import javax.swing.border.*;
import java.awt.*;
public class Test extends JApplet {
JPanel panel = new RainPanel();
TitledBorder border = new TitledBorder("JPanel Border");
public void init() {
panel.setBorder(border);
getContentPane().add(panel, BorderLayout.CENTER);
System.out.println("opaque = " + border.isBorderOpaque());
System.out.println(
"insets = " + border.getBorderInsets(panel));
}
}
class RainPanel extends JPanel {
public void paintComponent(Graphics g) {
Icon icon = new ImageIcon(getClass().getResource("rain.gif"));
Dimension size = getSize();
int patchW = icon.getIconWidth(),
patchH = icon.getIconHeight();
for(int r=0; r < size.width; r += patchW) {
for(int c=0; c < size.height; c += patchH)
icon.paintIcon(this, g, r, c);
}
}
}
5.1.4 边框包
5.1.5 边框接口
5.1.6 AbstractBoorder类
5.1.7 边框库——共享边框
例5-4 从边框库中获得边框
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
public class Test extends JApplet {
public void init() {
Container contentPane = getContentPane();
JPanel panel = new JPanel();
JPanel panel2 = new JPanel();
Border border = BorderFactory.createRaisedBevelBorder();
Border border2 = BorderFactory.createRaisedBevelBorder();
panel.setBorder(border);
panel2.setBorder(border2);
contentPane.add(panel, BorderLayout.NORTH);
contentPane.add(panel2, BorderLayout.SOUTH);
if(border == border2)
System.out.println("bevel borders are shared");
else
System.out.println("bevel borders are NOT shared");
}
}
5.1.8 替换内置边框
5.1.9 实现定制的边框
例5-5 HandleBorder类清单
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
public class HandleBorder extends AbstractBorder {
protected Color lineColor;
protected int thick;
public HandleBorder() {
this(Color.black, 6);
}
public HandleBorder(Color lineColor, int thick) {
this.lineColor = lineColor;
this.thick = thick;
}
public void paintBorder(Component c, Graphics g, int x,
int y, int w, int h) {
Graphics copy = g.create();
if(copy != null) {
try {
copy.translate(x,y);
paintRectangle(c,copy,w,h);
paintHandles(c,copy,w,h);
}
finally {
copy.dispose();
}
}
}
public Insets getBorderInsets() {
return new Insets(thick,thick,thick,thick);
}
protected void paintRectangle(Component c, Graphics g,
int w, int h) {
g.setColor(lineColor);
g.drawRect(thick/2,thick/2,w-thick-1,h-thick-1);
}
protected void paintHandles(Component c, Graphics g,
int w, int h) {
g.setColor(lineColor);
g.fillRect(0,0,thick,thick); // upper left
g.fillRect(w-thick,0,thick,thick); // upper right
g.fillRect(0,h-thick,thick,thick); // lower left
g.fillRect(w-thick,h-thick,thick,thick); // lower right
g.fillRect(w/2-thick/2,0,thick,thick); // mid top
g.fillRect(0,h/2-thick/2,thick,thick); // mid left
g.fillRect(w/2-thick/2,h-thick,thick,thick); // mid bottom
g.fillRect(w-thick,h/2-thick/2,thick,thick); // mid right
}
}
例5-6 使用定制边框
import javax.swing.*;
import javax.swing.border.*;
import java.awt.*;
import java.awt.event.*;
public class Test extends JApplet {
public void init() {
Container contentPane = getContentPane();
JPanel[] panels = { new JPanel(),
new JPanel(), new JPanel() };
Border[] borders = { new HandleBorder(),
new HandleBorder(Color.red, 8),
new HandleBorder(Color.blue, 10) };
contentPane.setLayout(
new FlowLayout(FlowLayout.CENTER,20,20));
for(int i=0; i < panels.length; ++i) {
panels[i].setPreferredSize(new Dimension(100,100));
panels[i].setBorder(borders[i]);
contentPane.add(panels[i]);
}
}
}
5.2 图标
例5-7 一个绘制图标的小应用程序
import com.sun.java.swing.JApplet;
import java.awt.Color;
import java.awt.Graphics;
public class IconTest extends JApplet {
ColorIcon redIcon;
ColorIcon blueIcon;
ColorIcon yellowIcon;
public void paint(Graphics g) {
redIcon.paintIcon(this, g, 0, 0);
blueIcon.paintIcon(this, g, redIcon.getIconWidth() + 10, 0);
yellowIcon.paintIcon(this, g, redIcon.getIconWidth() + 10 + blueIcon.getIconWidth() + 10, 0);
}
public IconTest() {
redIcon = new ColorIcon(Color.red, 50, 50);
blueIcon = new ColorIcon(Color.blue, 60, 60);
yellowIcon = new ColorIcon(Color.yellow, 70, 70);
}
}
例5-8 ColorIcon类清单
import java.awt.*;
import javax.swing.*;
class ColorIcon implements Icon {
private Color fillColor;
private int w, h;
public ColorIcon(Color fillColor, int w, int h) {
this.fillColor = fillColor;
this.w = w;
this.h = h;
}
public void paintIcon(Component c, Graphics g, int x, int y) {
g.setColor(Color.black);
g.drawRect(x, y, w-1, h-1);
g.setColor(fillColor);
g.fillRect(x+1, y+1, w-2, h-2);
}
public int getIconWidth() {
return w;
}
public int getIconHeight() {
return h;
}
}