《Java 2 图形设计卷Ⅱ- SWING》第6章 实用工具

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 BorlayoutBox

 

 

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

    图6-5 使用一个进度监视器(注:此为一可点击执行的.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 本章回顾

 

你可能感兴趣的:(java,swing)