今天研究了一个下午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();
}
});
}
}

解决方案 »

  1.   

    /**
     * @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里面去就可以了八看一下不。。不懂在联系
      

  2.   

    今天也是怎么做的,代码copy下来研究研究啊 :)
    俺也知道是Command Pattern, 但是对于javax.swing.undo包里的
    类的继承关系的缘由还不是太明白。对于这类框架类的东西的设计
    也不是太明白,比如java中的Observer Pattern的一个Observer类
    这个可以作为实现Observer Pattern的框架。这次这个undo也是一个
    例子。大一点的还有Structs,MVC的框架。等等
    还是小菜,继续研究 *^_^*