第12章 轻量容器
本章讨论如下Swing轻量容器:
·JPanel
·JRootPane
·JLayeredPane
·JTabbedPane
·JSplitPane
JPanel是AWT的Canvas和Panel类的继承类。文本和图形都可以绘制到JPanel实例中,并且JPanel实例可以用作一个通用容器。
JRootPane是一个包含在窗体、对话框、窗口、内部窗体和Swing小应用程序等Swing顶层容器中的容器。
JLayeredPane允许把它所包含的组件放置在不同的层中。层控制显示组件的深度。
JTabbedPane是一个能够包含多个组件的容器。JTabbedPane包含的多个组件一次只能显示一个。JTabbedPane的实例包含能够用于选取当前显示的组件的选项卡。
JSplitPane包含两个组件,这两个组件由一个分隔体所分隔。可以拖动分隔体以改变每个组件所占据的空间大小。
12.1 JPanel
JPanel是最简单的Swing组件之一;但它也是使用最多的组件之一。Swing在很多其他组件中使用了JPanel实例;例如,缺省时,JRootPane容器为它的内容窗格和玻璃窗格创建了JPanel实例,正如表12-1所反映的那样。
JPanel类具有简单容器显示图形的画布的双重功能。图12-1示出的小应用程序创建了三个JPanel实例:一个包含“Name:”选项卡和文本域的控制面板、一个专门用作显示文本和图形的画布的窗格,以及包含上述控制面板和画面的第三个面板。
例12-1中列出了图12-1中示出的小应用程序的代码。
例12-1 一个使用了三个JPanel实例的小应用程序
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Test extends JApplet {
public Test() {
Container contentPane = getContentPane();
JPanel panel = new JPanel(new BorderLayout());
JPanel controlPanel = new JPanel();
JPanel canvas = new Canvas();
canvas.setBorder(
BorderFactory.createLineBorder(Color.black));
controlPanel.add(new JLabel("Name:"));
controlPanel.add(new JTextField(20));
panel.add(controlPanel, BorderLayout.NORTH);
panel.add(canvas, BorderLayout.CENTER);
contentPane.add(panel);
}
}
class Canvas extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponent(g);
Dimension size = getSize();
g.setColor(Color.black);
g.drawLine(50,50,size.width,size.height);
g.drawArc(20,40,25,25,0,290);
g.drawString("A JPanel Used as a Canvas", 20, 20);
}
}
12.1.1 JPanel的属性
12.1.2 JPanel的事件
12.1.3 JPanel类总结
12.1.4 AWT兼容
12.2 JRootPane
12.2.1 RootPaneContainer接口
12.2.2 玻璃空格
例12-2 玻璃窗格测试小应用程序
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Test extends JApplet {
private Component glassPane = new CustomGlassPane();
public void init() {
JRadioButton rb = new JRadioButton();
JButton button = new JButton("show glass pane");
Container contentPane = getContentPane();
contentPane.setLayout(new FlowLayout());
contentPane.add(button);
rb.setIcon(new ImageIcon("duke_standing.gif"));
rb.setRolloverIcon(new ImageIcon("duke_waving.gif"));
setGlassPane(glassPane);
contentPane.add(rb);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
glassPane.setVisible(true);
}
});
}
}
class CustomGlassPane extends JPanel {
private JButton button;
private String displayString = "glass pane ... ";
public CustomGlassPane() {
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
setVisible(false);
}
});
}
public void paintComponent(Graphics g) {
Dimension size = getSize();
FontMetrics fm = g.getFontMetrics();
int sw = fm.stringWidth(displayString);
int fh = fm.getHeight();
g.setColor(Color.blue);
for(int row=fh; row < size.height; row += fh)
for(int col=0; col < size.width; col += sw)
g.drawString(displayString, col, row);
}
}
12.2.3 内容窗格
例12-3 一个定制的内容窗格
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ContentPaneTest extends JApplet {
private JButton button = new JButton("show glass pane");
public void init() {
setGlassPane(new CustomGlassPane(button));
setContentPane(new CustomContentPane(button));
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
getGlassPane().setVisible(true);
}
});
}
}
class CustomContentPane extends JPanel {
private ImageIcon rain = new ImageIcon("rain.gif");
private ImageIcon punch = new ImageIcon("punch.gif");
private int rainw = rain.getIconWidth();
private int rainh = rain.getIconHeight();
public CustomContentPane(JButton button) {
add(button);
add(new JLabel("I'm a JLabel in the Content Pane",
punch, SwingConstants.RIGHT));
}
public void paintComponent(Graphics g) {
Dimension size = getSize();
for(int row=0; row < size.height; row += rainh)
for(int col=0; col < size.width; col += rainw)
rain.paintIcon(this,g,col,row);
}
}
class CustomGlassPane extends JPanel {
private JButton button;
private Point ulhc = new Point(20,20), last;
private String displayString =
"I'm on the glass pane - drag me around!";
public CustomGlassPane(JButton b) {
button = b;
setOpaque(false);
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
last = e.getPoint();
}
public void mouseReleased(MouseEvent e) {
setVisible(false);
}
});
addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent e) {
Point drag = e.getPoint();
ulhc.x += drag.x - last.x;
ulhc.y += drag.y - last.y;
repaint();
last.x = drag.x;
last.y = drag.y;
}
});
}
public void paintComponent(Graphics g) {
FontMetrics fm = g.getFontMetrics();
int sw = fm.stringWidth(displayString);
int sh = fm.getHeight();
int ascent = fm.getAscent();
g.drawRect(ulhc.x, ulhc.y, sw + 10, sh + 10);
g.drawString(displayString,
ulhc.x + 5, ulhc.y + ascent + 5);
}
}
12.2.4 JRootPane属性
12.2.5 JRootPane事件
例12-4 一个传递事件的玻璃窗格
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import javax.swing.*;
import javax.swing.text.*;
public class Test extends JApplet {
Component glassPane = new AnnotationPane();
JCheckBox annotations = new JCheckBox("annotations");
public void init() {
createContainerHierarchy();
setupGlassPane();
}
private void createContainerHierarchy() {
Container contentPane = getContentPane();
JPanel controlPanel = new JPanel();
JTextArea textArea = new JTextArea();
JScrollPane scrollPane = new JScrollPane(textArea);
readFile(textArea.getDocument());
controlPanel.add(annotations);
contentPane.add(scrollPane, "Center"); // scroll pane
contentPane.add(controlPanel, "South"); // panel
textArea.addMouseListener(new MouseAdapter() {
public void mouseEntered(MouseEvent e) {
System.out.println("enter");
}
});
}
private void setupGlassPane() {
setGlassPane(glassPane);
annotations.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
if(e.getStateChange() == ItemEvent.SELECTED)
glassPane.setVisible(true);
else
glassPane.setVisible(false);
}
});
}
private void readFile(Document doc) {
try {
Reader in = new FileReader("Test.java");
char[] buff = new char[4096];
int next;
while ((next = in.read(buff, 0, buff.length)) != -1)
doc.insertString(
doc.getLength(), new String(buff, 0, next), null);
}
catch(Exception e) {
System.out.println("interruption");
}
}
}
class AnnotationPane extends JPanel {
private Icon annotations[] = {
new ImageIcon("annotation.gif"),
new ImageIcon("annotation_1.gif"),
new ImageIcon("annotation_2.gif")
};
public void paintComponent(Graphics g) {
annotations[0].paintIcon(this, g, 400, 50);
annotations[1].paintIcon(this, g, 10, 150);
annotations[2].paintIcon(this, g, 10, 265);
}
}
12.2.6 JRootPane类总结
12.2.7 AWT兼容
12.3 JLayoutPane
12.3.1 回顾轻量组件的层序
例12-5 添加到一个内容窗格中的按钮的程序
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Test extends JApplet {
Container cp = getContentPane();
private final Component[] comps = {
new JButton(), new JButton(),
new JButton(), new JButton(),
new JButton(), new JButton(),
};
public void init() {
cp.setLayout(null);
for(int i=0; i < comps.length; ++i) {
AbstractButton button = (AbstractButton)comps[i];
cp.add(button);
String t = "Button #";
t += i + " Index: " + getIndexOf(button);
button.setText(t);
button.setBounds(i*50, i*50, 350, 75);
System.out.println("Adding: " + button.getText());
}
}
private int getIndexOf(Component button) {
int ncomponents = cp.getComponentCount();
for(int i=0; i < ncomponents; ++i) {
Component c = cp.getComponent(i);
if(button == c)
return i;
}
return -1;
}
}
12.3.2 为组件分配器
例12-6 所包含在一个分层窗格中的组件分配到层中
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Test extends JApplet {
private JLayeredPane lp = new JLayeredPane();
private Integer[] layers = {
JLayeredPane.FRAME_CONTENT_LAYER,
JLayeredPane.DEFAULT_LAYER,
JLayeredPane.PALETTE_LAYER,
JLayeredPane.MODAL_LAYER,
JLayeredPane.POPUP_LAYER,
JLayeredPane.DRAG_LAYER,
};
private final Component[] comps = {
new JButton("Frame Content"), new JButton("Default"),
new JButton("Palette"), new JButton("Modal"),
new JButton("Popup"), new JButton("Drag"),
};
public void init() {
setContentPane(lp);
lp.setLayout(null);
for(int i=0; i < comps.length; ++i) {
AbstractButton button = (AbstractButton)comps[i];
System.out.println("Adding: " + button.getText());
lp.setLayer(button, layers[i].intValue());
lp.add(button);
}
for(int i=0; i < comps.length; ++i) {
AbstractButton button = (AbstractButton)comps[i];
String t = button.getText();
String replacement = new String("Layer: ");
replacement += t + "(" + lp.getLayer(button) + "),";
replacement += " Index: " + lp.getIndexOf(button);
button.setText(replacement);
button.setBounds(i*50, i*50, 350, 75);
}
}
}