第6章 实用工具
Swing包括许多实用工具,本章将介绍这些实用工具。其中有些实用工具(如计时器和由SwingUtilties类提供的static方法)在Swing内部使用,而进度监视器和进度监视器流等其他的实用工具则不是内容使用的。使用Swing的开发人员可以使用本章介绍的所有实用工具。
6.1 计时器
例6-1 使用Swing计时器
import java.awt.*; import java.awt.event.*; import javax.swing.*;
public class Test implements ActionListener { private int seconds=1;
public Test() { Timer oneSecondTimer = new Timer(1000, this); Timer timerWithInitialDelay = new Timer(2000, new TimerWithDelayListener()); Timer oneTimeTimer = new Timer(10000, new OneTimeListener());
timerWithInitialDelay.setInitialDelay(5000); oneTimeTimer.setRepeats(false);
oneSecondTimer.start(); timerWithInitialDelay.start(); oneTimeTimer.start(); } public void actionPerformed(ActionEvent e) { if(seconds == 0) System.out.println("Time: " + seconds + " second"); else System.out.println("Time: " + seconds + " seconds");
seconds++; } public static void main(String args[]) { new Test(); while(true); } } class TimerWithDelayListener implements ActionListener { public void actionPerformed(ActionEvent e) { System.out.println("Timer with Delay Ringing"); } } class OneTimeListener implements ActionListener { public void actionPerformed(ActionEvent e) { System.out.println("One Time Timer Ringing"); } }
例6-2 重载构造计时器时所指定的延迟
import java.awt.*; import java.awt.event.*; import javax.swing.*;
public class Test implements ActionListener { public Test() { Timer oneSecondTimer = new Timer(1000, this);
oneSecondTimer.setInitialDelay(10000); oneSecondTimer.setRepeats(false); oneSecondTimer.start(); } public void actionPerformed(ActionEvent e) { System.out.println("ring ..."); } public static void main(String args[]) { new Test(); while(true); } }
例6-3 计时器日志
import java.awt.*; import java.awt.event.*; import javax.swing.*;
public class Test implements ActionListener { public Test() { Timer.setLogTimers(true);
Timer oneSecondTimer = new MyTimer(1000, this); oneSecondTimer.start(); } public void actionPerformed(ActionEvent e) { System.out.println("ring ..."); } public static void main(String args[]) { new Test(); while(true); } } class MyTimer extends Timer { public MyTimer(int delay, ActionListener listener) { super(delay, listener); } public String toString() { return "MyTimer"; } }
例6-4 与单个计时器相关联的多个动作监听器
import java.awt.*; import java.awt.event.*; import javax.swing.*;
public class Test implements ActionListener { private int seconds=1;
public Test() { Timer oneSecondTimer = new Timer(1000, this);
oneSecondTimer.addActionListener(new SecondListener()); oneSecondTimer.addActionListener(new ThirdListener()); oneSecondTimer.start(); } public void actionPerformed(ActionEvent e) { if(seconds == 0) System.out.println("Time: " + seconds + " second"); else System.out.println("Time: " + seconds + " seconds"); seconds++; } public static void main(String args[]) { new Test(); while(true); } } class SecondListener implements ActionListener { public void actionPerformed(ActionEvent e) { System.out.println("Second Listener"); } } class ThirdListener implements ActionListener { public void actionPerformed(ActionEvent e) { System.out.println("Third Listener"); } }
例6-5 合并计时器事件
import java.awt.*; import java.awt.event.*; import javax.swing.*;
public class Test implements ActionListener { private boolean firstRing = true; private int ring = 1;
public Test() { Timer.setLogTimers(true);
Timer oneSecondTimer = new Timer(1000, this);
// comment out the following line for colaescing oneSecondTimer.setCoalesce(false);
System.out.println("Timer is coalescing: " + oneSecondTimer.isCoalesce());
oneSecondTimer.start(); } public void actionPerformed(ActionEvent e) { System.out.println("ring #" + ring++);
if(firstRing) { // simulate a time consuming operation by sleeping // for 10 seconds ... try { Thread.currentThread().sleep(10000); } catch(InterruptedException ex) { ex.printStackTrace(); } firstRing = false; } } public static void main(String args[]) { new Test(); while(true); } }
6.2 事件监听器列表
6.3 Swing实用工具
例6-6 计算两个矩形之间的差集、交集和并集
import java.awt.*; import java.awt.event.*; import javax.swing.*;
public class Test extends JApplet { Rectangle r1 = new Rectangle(20,20,150,75); Rectangle r2 = new Rectangle(100,40,100,150); Rectangle destination;
public Test() { destination = new Rectangle(r2);
// print out the intersection of r1 and r2 ...
System.out.println("Intersection: " + SwingUtilities.computeIntersection(r1.x,r1.y, r1.width,r1.height,destination)); System.out.println();
// print out the union of r1 and r2 ...
System.out.println("Union: " + SwingUtilities.computeUnion(r1.x,r1.y, r1.width,r1.height,destination)); System.out.println();
// print out the difference of r1 and r2 ...
Rectangle[] difference = SwingUtilities.computeDifference(r1, r2);
System.out.println("Difference:");
for(int i=0; i < difference.length; ++i) { System.out.println(difference[i]); } } public void paint(Graphics g) { g.setColor(Color.red); g.fillRect(r1.x, r1.y, r1.width, r1.height);
g.setColor(Color.yellow); g.fillRect(r2.x, r2.y, r2.width, r2.height); } }
<applet archive="s06_tu02.jar" code="Test.class" width="600" height="550"><param name="height" value="550"> <param name="archive" value="s06_tu02.jar"> <param name="width" value="600"> <param name="code" value="Test.class"> <param name="codeBase" value="http://www.web.nyist.net/~rf/gui/"></applet> 图6-2 转换坐标系统
例6-7 转换鼠标坐标
import java.awt.*; import java.awt.event.*; import javax.swing.*;
public class Test extends JApplet { private Point lastScreenPt = null; private final Container contentPane = getContentPane(); private PanelWithString outer = new PanelWithString(Color.orange), inner = new PanelWithString(Color.red), innermost = new PanelWithString(Color.yellow);
public Test() { Font font = new Font("Times-Roman", Font.ITALIC, 26);
contentPane.setLayout(new OverlayLayout(contentPane)); contentPane.add(innermost); contentPane.add(inner); contentPane.add(outer);
innermost.setMaximumSize(new Dimension(350,50)); inner.setMaximumSize(new Dimension(450,200)); outer.setMaximumSize(new Dimension(550,400));
setFont(font); innermost.setFont(font); inner.setFont(font); outer.setFont(font);
contentPane.addMouseMotionListener( new MouseMotionAdapter() { public void mouseMoved(MouseEvent e) { Point pt = e.getPoint();
outer.setString(SwingUtilities.convertPoint( contentPane, pt, outer).toString());
inner.setString(SwingUtilities.convertPoint( contentPane, pt, inner).toString());
innermost.setString(SwingUtilities.convertPoint( contentPane, pt, innermost).toString());
SwingUtilities.convertPointToScreen( pt, contentPane);
lastScreenPt = pt; repaint(); } }); } public void paint(Graphics g) { super.paint(g);
if(lastScreenPt != null) { String s = new String("Screen: " + lastScreenPt);
g.setColor(getForeground()); g.drawString(s,10,g.getFontMetrics().getHeight());
SwingUtilities.convertPointFromScreen(lastScreenPt, contentPane);
s = "Content Pane: " + lastScreenPt;
g.drawString(s,10,g.getFontMetrics().getHeight()*2); } else { g.setColor(getForeground()); g.drawString("MOVE THE MOUSE IN HERE",10, g.getFontMetrics().getHeight()); } } } class PanelWithString extends JPanel { String s; Color color;
public PanelWithString(Color color) { this.color = color; } public void setString(String s) { this.s = s; } public void paintComponent(Graphics g) { super.paintComponent(g);
Dimension size = getSize();
g.setColor(color); g.fillRect(0,0,size.width,size.height);
if(s != null) { g.setColor(getForeground()); g.drawString(s,10,g.getFontMetrics().getHeight()); } } }
6.4 Swing常量
6.5 Borlayout和Box类
6.5.1 BoxLayout类
<applet archive="s06_tu03.jar" code="Test.class" width="400" height="250"><param name="height" value="250"> <param name="archive" value="s06_tu03.jar"> <param name="width" value="400"> <param name="code" value="Test.class"> <param name="codeBase" value="http://www.web.nyist.net/~rf/gui/"></applet> 图6-3 两个使用BoxLayout的容器
例6-8 使用BoxLayout
import java.awt.*; import java.awt.event.*; import javax.swing.*;
public class Test extends JApplet { public Test() { Container contentPane = getContentPane(); ContainerWithBoxLayout yaxis = new ContainerWithBoxLayout(BoxLayout.Y_AXIS);
ContainerWithBoxLayout xaxis = new ContainerWithBoxLayout(BoxLayout.X_AXIS);
contentPane.setLayout(new FlowLayout());
xaxis.add(new JButton(new ImageIcon("reach.gif"))); xaxis.add(new JButton(new ImageIcon("punch.gif"))); xaxis.add(new JButton(new ImageIcon("open_hand.gif")));
yaxis.add(new JButton(new ImageIcon("ladybug.gif"))); yaxis.add(new JButton(new ImageIcon("crab.gif"))); yaxis.add(new JButton(new ImageIcon("frog.gif"))); yaxis.add(new JButton(new ImageIcon("snail.gif")));
contentPane.add(xaxis); contentPane.add(yaxis); } } class ContainerWithBoxLayout extends JPanel { public ContainerWithBoxLayout(int orientation) { setLayout(new BoxLayout(this, orientation)); } }
6.5.2 Box类
例6-9 使用水平和垂直的膨胀体
6.6 进度监视器
6.6.1 ProgressMonitor
使用一个进度监视器(注:此为一可点击执行的.jar文件,但需要下载到你的电脑上方可点击执行)
例6-10 使用一个进度监视器
import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.util.*; import java.io.*;
public class Test extends JFrame { private JButton readButton = new JButton("read file"); private BufferedInputStream in; private ProgressMonitor pm; private String fileName = "Test.java";
public Test() { final Container contentPane = getContentPane();
contentPane.setLayout(new FlowLayout()); contentPane.add(readButton);
readButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { try { in = new BufferedInputStream( new FileInputStream(fileName));
pm = new ProgressMonitor(contentPane, "Reading File:", fileName, 0, in.available()); } catch(FileNotFoundException fnfx) { fnfx.printStackTrace(); } catch(IOException iox) { iox.printStackTrace(); }
ReadThread t = new ReadThread(); t.start(); } }); } class ReadThread extends Thread { int i, cnt=0; String s;
public void run() { try { readButton.setEnabled(false);
while(!pm.isCanceled() && (i = in.read()) != -1) { try { Thread.currentThread().sleep(25); } catch(InterruptedException ex) { ex.printStackTrace(); } System.out.print((char)i);
SwingUtilities.invokeLater(new Runnable(){ public void run() { pm.setProgress(++cnt); } }); } if(pm.isCanceled()) JOptionPane.showMessageDialog( Test.this, "Operation Canceled!", "Cancellation", JOptionPane.ERROR_MESSAGE); } catch(IOException ex) { ex.printStackTrace(); } finally { try { in.close(); } catch(IOException ex2) { ex2.printStackTrace(); } } readButton.setEnabled(true); } } public static void main(String args[]) { GJApp.launch(new Test(), "Using Progress Monitors",300,300,450,300); } } class GJApp extends WindowAdapter { static private JPanel statusArea = new JPanel(); static private JLabel status = new JLabel(" "); static private ResourceBundle resources;
public static void launch(final JFrame f, String title, final int x, final int y, final int w, int h) { launch(f,title,x,y,w,h,null); } public static void launch(final JFrame f, String title, final int x, final int y, final int w, int h, String propertiesFilename) { f.setTitle(title); f.setBounds(x,y,w,h); f.setVisible(true);
statusArea.setBorder(BorderFactory.createEtchedBorder()); statusArea.setLayout(new FlowLayout(FlowLayout.LEFT,0,0)); statusArea.add(status); status.setHorizontalAlignment(JLabel.LEFT);
f.setDefaultCloseOperation( WindowConstants.DISPOSE_ON_CLOSE);
if(propertiesFilename != null) { resources = ResourceBundle.getBundle( propertiesFilename, Locale.getDefault()); }
f.addWindowListener(new WindowAdapter() { public void windowClosed(WindowEvent e) { System.exit(0); } }); } static public JPanel getStatusArea() { return statusArea; } static public void showStatus(String s) { status.setText(s); } static Object getResource(String key) { if(resources != null) { return resources.getString(key); } return null; } }
6.6.2 PropressMonitorInputStream
例6-11 使用ProgressMonitorInputStream
import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.util.*; import java.io.*;
public class Test extends JFrame { private ProgressMonitorInputStream in; private JButton readButton = new JButton("read file");
public Test() { final Container contentPane = getContentPane(); final String fileName = "Test.java";
contentPane.setLayout(new FlowLayout()); contentPane.add(readButton);
readButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { try { in = new ProgressMonitorInputStream( contentPane, "Reading " + fileName, new FileInputStream(fileName)); } catch(FileNotFoundException ex) { ex.printStackTrace(); }
ReadThread t = new ReadThread(); readButton.setEnabled(false); t.start(); } }); } class ReadThread extends Thread { public void run() { int i;
try { while((i = in.read()) != -1) { System.out.print((char)i); try { Thread.currentThread().sleep(10); } catch(Exception ex) { ex.printStackTrace(); } } in.close(); } catch(IOException ex) { JOptionPane.showMessageDialog( Test.this, "Operation Canceled!", "Cancellation", JOptionPane.ERROR_MESSAGE); } readButton.setEnabled(true); } } public static void main(String args[]) { GJApp.launch(new Test(), "Using ProgressMonitorInputStream", 300,300,450,300); } } class GJApp extends WindowAdapter { static private JPanel statusArea = new JPanel(); static private JLabel status = new JLabel(" "); static private ResourceBundle resources;
public static void launch(final JFrame f, String title, final int x, final int y, final int w, int h) { launch(f,title,x,y,w,h,null); } public static void launch(final JFrame f, String title, final int x, final int y, final int w, int h, String propertiesFilename) { f.setTitle(title); f.setBounds(x,y,w,h); f.setVisible(true);
statusArea.setBorder(BorderFactory.createEtchedBorder()); statusArea.setLayout(new FlowLayout(FlowLayout.LEFT,0,0)); statusArea.add(status); status.setHorizontalAlignment(JLabel.LEFT);
f.setDefaultCloseOperation( WindowConstants.DISPOSE_ON_CLOSE);
if(propertiesFilename != null) { resources = ResourceBundle.getBundle( propertiesFilename, Locale.getDefault()); }
f.addWindowListener(new WindowAdapter() { public void windowClosed(WindowEvent e) { System.exit(0); } }); } static public JPanel getStatusArea() { return statusArea; } static public void showStatus(String s) { status.setText(s); } static Object getResource(String key) { if(resources != null) { return resources.getString(key); } return null; } }
6.7 撤消/重复
6.7.1一个简单的撤消/重复样例
例6-12 一个简单的撤消/重复样例
import javax.swing.*; import javax.swing.undo.*; import java.awt.*; import java.awt.event.*;
public class Test extends JApplet { private JPanel colorPanel = new JPanel(); private BackgroundColorEdit undo = new BackgroundColorEdit(); private Color oldColor;
public void init() { colorPanel.setBorder( BorderFactory.createTitledBorder( "Change color and subsequently undo " + "from the Edit menu"));
makeMenuBar(); getContentPane().add(colorPanel, BorderLayout.CENTER); } private void makeMenuBar() { JMenuBar menuBar = new JMenuBar(); JMenu editMenu = new JMenu("Edit");
editMenu.add(new SetColorAction()); editMenu.add(new UndoAction());
menuBar.add(editMenu); setJMenuBar(menuBar); } class SetColorAction extends AbstractAction { public SetColorAction() { super("Set color ..."); } public void actionPerformed(ActionEvent e) { Color color = JColorChooser.showDialog( Test.this, // parent component "Pick A Color", // dialog title null); // initial color
if(color != null) { oldColor = colorPanel.getBackground(); colorPanel.setBackground(color); } } } class UndoAction extends AbstractAction { public UndoAction() { putValue(Action.NAME, undo.getUndoPresentationName()); } public void actionPerformed(ActionEvent e) { String name = (String)getValue(Action.NAME); boolean isUndo = name.equals( undo.getUndoPresentationName());
if(isUndo) { undo.undo(); putValue(Action.NAME, undo.getRedoPresentationName()); } else { undo.redo(); putValue(Action.NAME, undo.getUndoPresentationName()); } } } class BackgroundColorEdit extends AbstractUndoableEdit { public void undo() throws CannotUndoException { super.undo(); toggleColor(); } public void redo() throws CannotRedoException { super.redo(); toggleColor(); } public String getUndoPresentationName() { return "Undo"; } public String getRedoPresentationName() { return "Redo"; } private void toggleColor() { Color color = colorPanel.getBackground(); colorPanel.setBackground(oldColor); oldColor = color; } } }
6.7.2 UndoableEditSupport
例6-13 使用UndoableEditSupport
import javax.swing.*; import javax.swing.event.*; import javax.swing.undo.*; import java.awt.*; import java.awt.event.*;
public class Test extends JApplet { private ColorPanel colorPanel = new ColorPanel(); private UndoAction undoAction = new UndoAction();
public void init() { colorPanel.setBorder( BorderFactory.createTitledBorder( "Change color and subsequently undo " + "from the Edit menu"));
makeMenuBar(); colorPanel.addUndoableEditListener(undoAction); getContentPane().add(colorPanel, BorderLayout.CENTER); } private void makeMenuBar() { JMenuBar menuBar = new JMenuBar(); JMenu editMenu = new JMenu("Edit");
editMenu.add(new SetColorAction()); editMenu.add(undoAction);
menuBar.add(editMenu); setJMenuBar(menuBar); } class UndoAction extends AbstractAction implements UndoableEditListener { UndoableEdit lastEdit;
public UndoAction() { putValue(Action.NAME, "Undo"); setEnabled(false); } public void actionPerformed(ActionEvent e) { String name = (String)getValue(Action.NAME); boolean isUndo = name.equals( lastEdit.getUndoPresentationName()); if(isUndo) { lastEdit.undo(); putValue(Action.NAME, lastEdit.getRedoPresentationName()); } else { lastEdit.redo(); putValue(Action.NAME, lastEdit.getUndoPresentationName()); } } public void undoableEditHappened(UndoableEditEvent e) { lastEdit = e.getEdit();
putValue(Action.NAME, lastEdit.getUndoPresentationName());
if(lastEdit.canUndo()) setEnabled(true); } } class SetColorAction extends AbstractAction { public SetColorAction() { super("Set color ..."); } public void actionPerformed(ActionEvent e) { Color color = JColorChooser.showDialog( Test.this, // parent component "Pick A Color", // dialog title null); // initial color
if(color != null) { colorPanel.setBackground(color); } } } } class ColorPanel extends JPanel { UndoableEditSupport support; BackgroundColorEdit edit = new BackgroundColorEdit(); Color oldColor;
public void addUndoableEditListener( UndoableEditListener l) { support.addUndoableEditListener(l); } public void removeUndoableEditListener( UndoableEditListener l) { support.removeUndoableEditListener(l); } public void setBackground(Color color) { oldColor = getBackground(); super.setBackground(color);
if(support == null) support = new UndoableEditSupport();
support.postEdit(edit); } class BackgroundColorEdit extends AbstractUndoableEdit { public void undo() throws CannotUndoException { super.undo(); toggleColor(); } public void redo() throws CannotRedoException { super.redo(); toggleColor(); } public String getUndoPresentationName() { return "Undo Background Color Change"; } public String getRedoPresentationName() { return "Redo Background Color Change"; } private void toggleColor() { Color color = getBackground(); setBackground(oldColor); oldColor = color; } } }
6.7.3组合编辑
例6-14 使用组合编辑
import javax.swing.*; import javax.swing.event.*; import javax.swing.undo.*; import java.awt.*; import java.awt.event.*;
public class Test extends JApplet { private UndoableList list = new UndoableList(); private JScrollPane scrollPane = new JScrollPane(list);
private JButton addButton = new JButton("Add Item"), endButton = new JButton("End"), undoButton = new JButton("Undo");
private UndoAction undoAction = new UndoAction(); private CompoundEdit compoundEdit = new CompoundEdit(); private int cnt=0;
public void init() { Container contentPane = getContentPane();
contentPane.setLayout(new FlowLayout()); contentPane.add(addButton); contentPane.add(endButton); contentPane.add(undoButton); contentPane.add(scrollPane);
scrollPane.setPreferredSize(new Dimension(150,150)); list.addUndoableEditListener(undoAction);
endButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { compoundEdit.end(); updateButtonsEnabledState(); } }); addButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { list.undoableAdd("item #" + cnt++); updateButtonsEnabledState(); } }); undoButton.addActionListener(undoAction);
endButton.setEnabled(false); undoButton.setEnabled(false); } private void updateButtonsEnabledState() { boolean inProgress = compoundEdit.isInProgress();
endButton.setEnabled(inProgress); addButton.setEnabled(inProgress);
if(undoButton.getText().equals("Undo")) undoButton.setEnabled(compoundEdit.canUndo()); else undoButton.setEnabled(compoundEdit.canRedo()); } class UndoAction extends AbstractAction implements UndoableEditListener {
public UndoAction() { putValue(Action.NAME, "Undo"); } public void actionPerformed(ActionEvent e) { String name = undoButton.getText(); boolean isUndo = name.equals("Undo");
if(isUndo) compoundEdit.undo(); else compoundEdit.redo();
undoButton.setText(isUndo ? "Redo" : "Undo"); } public void undoableEditHappened(UndoableEditEvent e) { UndoableEdit edit = e.getEdit(); compoundEdit.addEdit(edit); endButton.setEnabled(true); } } } class UndoableList extends JList { UndoableEditSupport support = new UndoableEditSupport(); DefaultListModel model;
public UndoableList() { setModel(model = new DefaultListModel()); } public void addUndoableEditListener(UndoableEditListener l) { support.addUndoableEditListener(l); } public void removeUndoableEditListener( UndoableEditListener l) { support.removeUndoableEditListener(l); } public void undoableAdd(Object s) { model.addElement(s); support.postEdit(new AddItemEdit()); } class AddItemEdit extends AbstractUndoableEdit { Object lastItemAdded;
public void undo() throws CannotUndoException { super.undo(); lastItemAdded = model.getElementAt(model.getSize()-1); model.removeElement(lastItemAdded); } public void redo() throws CannotRedoException { super.redo(); model.addElement(lastItemAdded); } } }
6.7.4 UndoManager
6.7.5状态编辑
例6-15 使用状态编辑
import javax.swing.*; import javax.swing.event.*; import javax.swing.undo.*; import java.awt.*; import java.awt.event.*; import java.util.*;
public class Test extends JApplet { private TextFieldPanel panel = new TextFieldPanel(); private StateEdit stateEdit;
private JButton startButton = new JButton("Start Edit"), endButton = new JButton("End Edit"), undoButton = new JButton("Undo");
public void init() { Container contentPane = getContentPane();
contentPane.setLayout(new FlowLayout()); contentPane.add(startButton); contentPane.add(endButton); contentPane.add(undoButton); contentPane.add(panel);
endButton.setEnabled(false); undoButton.setEnabled(false);
startButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { stateEdit = new StateEdit(panel); endButton.setEnabled(true); startButton.setEnabled(false); } }); endButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { stateEdit.end(); undoButton.setEnabled(true); endButton.setEnabled(false); } }); undoButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { String name = undoButton.getText(); boolean isUndo = name.equals("Undo");
if(isUndo) stateEdit.undo(); else stateEdit.redo();
undoButton.setText(isUndo ? "Redo" : "Undo"); } }); } } class TextFieldPanel extends JPanel implements StateEditable { JTextField[] fields = new JTextField[] { new JTextField("text field 1"), new JTextField("text field 2"), new JTextField("text field 3"), new JTextField("text field 4"), };
public TextFieldPanel() { setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
for(int i=0; i < fields.length; ++i) add(fields[i]); } public void storeState(Hashtable hashtable) { for(int i=0; i < fields.length; ++i) hashtable.put(fields[i], fields[i].getText()); } public void restoreState(Hashtable hashtable) { Enumeration keys = hashtable.keys();
while(keys.hasMoreElements()) { JTextField field = (JTextField)keys.nextElement(); field.setText((String)hashtable.get(field)); } } }
6.8 本章回顾