今天研究了一个下午undo,但是还是实现不了多次的连续不断的undo。
下面这段代码只能实现,一次undo。比如打一个s,点undo,s消失,再
点一下s,又出现。
应该怎么搞,才能实现多次的undo呢??import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.undo.*;
import javax.swing.event.*;
import java.util.*;public class TestUndo
{
public static void main(String[] args)
{
JFrame frame = new MyFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.show();
}
}class MyFrame extends JFrame
{
private MyTextArea text; public MyFrame()
{
Toolkit t = Toolkit.getDefaultToolkit();
Dimension d = t.getScreenSize();
int width = d.width;
int height = d.height; setBounds(width / 4, height/ 4, width / 2, height / 2); Container c = getContentPane();
JButton b1 = new JButton("Undo");
JButton b2 = new JButton("Redo");
JPanel p = new JPanel();
p.add(b1);
p.add(b2);
b1.addActionListener(new UndoAction());
b2.addActionListener(new RedoAction());
c.add(p, BorderLayout.NORTH); text = new MyTextArea(10, 50);
if (text == null)
{
System.out.println("NULL@@@@@@");
}
text.setText("Hello, Undo");
c.add(text, BorderLayout.CENTER);
}
class UndoAction extends AbstractAction
{
public void actionPerformed(ActionEvent e)
{ text.undo();
}
} class RedoAction extends AbstractAction
{
public void actionPerformed(ActionEvent e)
{
text.redo();
}
}
}class MyTextArea extends TextArea implements StateEditable
{
private final static String KEY_STATE = "UndoableTextAreaKey";
private boolean textChanged = false;
private UndoManager undoManager;
private StateEdit currentEdit; public MyTextArea(int x, int y)
{
super(x, y);
initUndoable();
} public boolean undo()
{
try
{
undoManager.undo();
return true;
}
catch(Exception e)
{
e.printStackTrace();
return false;
}
} public boolean redo()
{
try
{
undoManager.redo();
return true;
}
catch(Exception e)
{
e.printStackTrace();
return false;
}
} public void storeState(Hashtable state)
{
state.put(KEY_STATE, getText());
} public void restoreState(Hashtable state)
{
Object data = state.get(KEY_STATE);
if (data != null)
{
setText((String)data);
}
} private void takeSnapshot()
{
if (textChanged)
{
currentEdit.end();
undoManager.addEdit(currentEdit);
textChanged = false;
currentEdit = new StateEdit(this);
}
} private void initUndoable()
{
undoManager = new UndoManager();
undoManager.setLimit(100);
currentEdit = new StateEdit(this);
addKeyListener(new KeyAdapter()
{
public void keyPressed(KeyEvent e)
{
if (e.isActionKey())
{
takeSnapshot();
}
}
});
addFocusListener(new FocusAdapter()
{
public void focusLost(FocusEvent e)
{
takeSnapshot();
}
}); addTextListener(new TextListener()
{
public void textValueChanged(TextEvent e)
{
textChanged = true;
takeSnapshot();
}
});
}
}
下面这段代码只能实现,一次undo。比如打一个s,点undo,s消失,再
点一下s,又出现。
应该怎么搞,才能实现多次的undo呢??import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.undo.*;
import javax.swing.event.*;
import java.util.*;public class TestUndo
{
public static void main(String[] args)
{
JFrame frame = new MyFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.show();
}
}class MyFrame extends JFrame
{
private MyTextArea text; public MyFrame()
{
Toolkit t = Toolkit.getDefaultToolkit();
Dimension d = t.getScreenSize();
int width = d.width;
int height = d.height; setBounds(width / 4, height/ 4, width / 2, height / 2); Container c = getContentPane();
JButton b1 = new JButton("Undo");
JButton b2 = new JButton("Redo");
JPanel p = new JPanel();
p.add(b1);
p.add(b2);
b1.addActionListener(new UndoAction());
b2.addActionListener(new RedoAction());
c.add(p, BorderLayout.NORTH); text = new MyTextArea(10, 50);
if (text == null)
{
System.out.println("NULL@@@@@@");
}
text.setText("Hello, Undo");
c.add(text, BorderLayout.CENTER);
}
class UndoAction extends AbstractAction
{
public void actionPerformed(ActionEvent e)
{ text.undo();
}
} class RedoAction extends AbstractAction
{
public void actionPerformed(ActionEvent e)
{
text.redo();
}
}
}class MyTextArea extends TextArea implements StateEditable
{
private final static String KEY_STATE = "UndoableTextAreaKey";
private boolean textChanged = false;
private UndoManager undoManager;
private StateEdit currentEdit; public MyTextArea(int x, int y)
{
super(x, y);
initUndoable();
} public boolean undo()
{
try
{
undoManager.undo();
return true;
}
catch(Exception e)
{
e.printStackTrace();
return false;
}
} public boolean redo()
{
try
{
undoManager.redo();
return true;
}
catch(Exception e)
{
e.printStackTrace();
return false;
}
} public void storeState(Hashtable state)
{
state.put(KEY_STATE, getText());
} public void restoreState(Hashtable state)
{
Object data = state.get(KEY_STATE);
if (data != null)
{
setText((String)data);
}
} private void takeSnapshot()
{
if (textChanged)
{
currentEdit.end();
undoManager.addEdit(currentEdit);
textChanged = false;
currentEdit = new StateEdit(this);
}
} private void initUndoable()
{
undoManager = new UndoManager();
undoManager.setLimit(100);
currentEdit = new StateEdit(this);
addKeyListener(new KeyAdapter()
{
public void keyPressed(KeyEvent e)
{
if (e.isActionKey())
{
takeSnapshot();
}
}
});
addFocusListener(new FocusAdapter()
{
public void focusLost(FocusEvent e)
{
takeSnapshot();
}
}); addTextListener(new TextListener()
{
public void textValueChanged(TextEvent e)
{
textChanged = true;
takeSnapshot();
}
});
}
}
* @author Wu Taihong
*/
public class CreateNewShape extends AbstractUndoableEdit
{
private DrawingModel _storedModel = null;
private MyShape _shapeElement = null;
private int _index = -1;
/**
*
*/
public CreateNewShape(DrawingModel model, MyShape element, int index)
{
super();
// TODO Auto-generated constructor stub
_storedModel = model;
_shapeElement = element;
_index = index;
}
public void undo() throws CannotUndoException
{
_storedModel.get_shapes().remove(_index);
}
public void redo() throws CannotRedoException
{
_storedModel.get_shapes().add(_index, _shapeElement);
}
public boolean canUndo()
{
boolean returnBoolean = true;
return returnBoolean;
}
public boolean canRedo()
{
boolean returnBoolean = true;
return returnBoolean;
}
public String getPresentationName()
{
String returnString = "Create New Shape";
return returnString;
}
}
/**
* @author Wu Taihong
*/
public class RemoveShape extends AbstractUndoableEdit
{ private DrawingModel _storedModel = null;
private MyShape _shapeElement = null;
private int _index = -1;
/**
*
*/
public RemoveShape(DrawingModel model, MyShape element, int index)
{
super();
// TODO Auto-generated constructor stub
_storedModel = model;
_shapeElement = element;
_index = index;
}
public void undo() throws CannotUndoException
{
_storedModel.get_shapes().add(_index, _shapeElement);
}
public void redo() throws CannotRedoException
{
_storedModel.get_shapes().remove(_index);
}
public boolean canUndo()
{
boolean returnBoolean = true;
return returnBoolean;
}
public boolean canRedo()
{
boolean returnBoolean = true;
return returnBoolean;
}
public String getPresentationName()
{
String returnString = null;
return returnString;
}
}
/**
* @author Wu Taihong
*/
public class MyFunctionPane extends JPanel implements ConstantValues, ViewInterface
{
public ASDrawing _parent = null;
private JList _shapeList = null;
private JButton _deleteShapeButton = null;
private JScrollPane _scrolPane = null;
private int _lastListSelected = -1;
private int _currentListSelected = -1;
/**
*
*/
public MyFunctionPane(ASDrawing parent)
{
super();
// TODO Auto-generated constructor stub
_parent = parent;
init();
}
/**
* @param isDoubleBuffered
*/
public MyFunctionPane(ASDrawing parent, boolean isDoubleBuffered)
{
super(isDoubleBuffered);
// TODO Auto-generated constructor stub
_parent = parent;
init(); }
/**
* @param layout
*/
public MyFunctionPane(ASDrawing parent, LayoutManager layout)
{
super(layout);
// TODO Auto-generated constructor stub
_parent = parent;
init(); }
/**
* @param layout
* @param isDoubleBuffered
*/
public MyFunctionPane(ASDrawing parent, LayoutManager layout, boolean isDoubleBuffered)
{
super(layout, isDoubleBuffered);
// TODO Auto-generated constructor stub
_parent = parent;
init(); }
public void init()
{
this.setLayout(new BorderLayout());
_shapeList = new JList();
_deleteShapeButton = new JButton("Delete Shape");
_deleteShapeButton.setSelected(false);
//change selection model to single selection
_shapeList.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
addComponents();
updateView();
addActions();
}
public void updateListContent()
{
Vector tempModel = _parent.get_model().get_shapes();
Vector listVector = new Vector();
for(int i=0;i<tempModel.size();i++)
{
MyShape tempShape = (MyShape)tempModel.get(i);
String tempShapeName = tempShape.getShapeName();
if(DEBUG>3)
{
System.out.println(this.getClass().getName()+": addListContent: "+i+":"+tempShapeName);
}
listVector.add(tempShapeName);
}
_shapeList.setListData(listVector);
}
public void addComponents()
{
_scrolPane = new JScrollPane(_shapeList);
this.add("North",new JLabel("Shapes List"));
this.add("Center",_scrolPane);
this.add("South",_deleteShapeButton);
}
public void addActions()
{
_shapeList.getSelectionModel().addListSelectionListener(new ListAction(this));
_deleteShapeButton.addActionListener(new DeleteShapeButtonAction(this));
}
/**
* @return Returns the _shapeList.
*/
public JList get_shapeList()
{
return _shapeList;
}
public void actionListselectChanged(int index, int lastIndex)
{
MyShape tempShape = null;
_currentListSelected = index;
_lastListSelected = lastIndex;
if(lastIndex >= 0)
{
tempShape = (MyShape)_parent.get_model().get_shapes().get(lastIndex);
tempShape.set_storedColor();
}
tempShape = (MyShape)_parent.get_model().get_shapes().get(index);
tempShape.setColor(highLightColor);
_parent.get_drawPane().repaint();
}
public void actionDeleteShapeButton(int index)
{
Vector tempShapes = _parent.get_model().get_shapes();
MyShape tempShape = (MyShape)tempShapes.get(index);
// reset the shape color to default color or redo will be the high light color
tempShape.set_storedColor();
// TODO redo - undo
// however, give the the element is ID number
UndoableEdit edit = new RemoveShape(_parent.get_model(), tempShape,
index);
//perform the operation
tempShapes.remove(index);
// TODO redo - undo
// notify the listeners
_parent.get_undoSupport().postEdit(edit);
_parent.get_functionPane().updateView();
_parent.updateView();
}
/**
* @return Returns the _lastListSelected.
*/
public int get_lastListSelected()
{
return _lastListSelected;
}
/**
* @return Returns the _currentListSelected.
*/
public int get_currentListSelected()
{
return _currentListSelected;
} /* (non-Javadoc)
* @see AuthoringSystemDrawTool.ViewInterface#updateValues()
*/
public void updateView()
{
// TODO Auto-generated method stub
updateListContent();
} /* (non-Javadoc)
* @see dissertation.ViewInterface#getModel()
*/
public ModelInterface getModel()
{
// TODO Auto-generated method stub
return null;
}
}//TODO undo - redo
/**
* An undo/redo adpater. The adpater is notified when
* an undo edit occur(e.g. add or remove from the list)
* The adptor extract the edit from the event, add it
* to the UndoManager, and refresh the GUI
*/
class UndoAdapter implements UndoableEditListener
{
public void undoableEditHappened(UndoableEditEvent evt)
{
UndoableEdit edit = evt.getEdit();
_undoManager.addEdit(edit);
updateView();
}
}
然后那个undoSupport.addUndoableEditListener(new UndoAdapter());
代码比较的多。。很早以前写的东西了。。现在拿了3个class 出来。。应该也差不多了。。就是为每个动作都创建1个类。然后放undosupport里面去就可以了八看一下不。。不懂在联系
俺也知道是Command Pattern, 但是对于javax.swing.undo包里的
类的继承关系的缘由还不是太明白。对于这类框架类的东西的设计
也不是太明白,比如java中的Observer Pattern的一个Observer类
这个可以作为实现Observer Pattern的框架。这次这个undo也是一个
例子。大一点的还有Structs,MVC的框架。等等
还是小菜,继续研究 *^_^*