java ctrl z_ctrl+z的JAVA实现,借助了命令模式(command pattern)

packageundoRedo;

importjava.awt.Frame;

import java.awt.event.*;

public class MainFrame extendsFrame {

private staticUndoableTextArea text;

private staticItsukyuQuatation panel;

publicMainFrame(String title)

{

super(title);

}

public static voidmain(String[] args)

{

//构造可撤消的textArea

text = new UndoableTextArea("Your text here");

//构造panel

panel = newItsukyuQuatation(text);

//构造frame

MainFrame frame = new MainFrame("测试undo和redo");

//增加窗体关闭事件

frame.addWindowListener(newWindowAdapter()

{

public voidwindowClosing(WindowEvent e)

{

System.exit(0);

}

});

frame.add(panel);

frame.setSize(300,300);

frame.setVisible(true);

}

}

ItsukyuQuatation类:面板类,里面包括undo和redo两个按钮,类似于命令模式中的摇控器。实现了ActionListener接口。

packageundoRedo;

importjava.awt.BorderLayout;

importjava.awt.Panel;

importjava.awt.event.ActionEvent;

importjava.awt.event.ActionListener;

public class ItsukyuQuatation extends Panel implementsActionListener {

private finalCommand undo;

private finalCommand redo;

publicItsukyuQuatation(UndoableTextArea text)

{

this.setLayout(newBorderLayout());

Panel toolbar = newPanel();

undo = newUndoCommand(text);

redo = newRedoCommand(text);

undo.addActionListener(this);

redo.addActionListener(this);

toolbar.add(undo);

toolbar.add(redo);

this.add(toolbar,"North");

this.add(text,"Center");

}

public voidactionPerformed(ActionEvent e) {

//TODO Auto-generated method stub

Command cmd =(Command)e.getSource();

cmd.execute();

}

}

UndoableTextArea类:类似于命令模式中的电视机类。实现了StateEditable接口,因此该类具有可撤销和重做的功能。重载的storeState和restoreState即是把文本中的内容放到hashTable里去。

该类是最核心的类,实现ctrl+z的原理简单说就是UndoManger.edits是一个Vector动态数组,对每次的按键动作,都会存储一份当前的文本内容到数据。当点击undo按钮,

数组索引(UnoManager类的indexOfNextAdd变量)前移一位,取得前一状态的文本内容。点击redo按钮,数组索引后移一位,取后一状态的文本内容。但是各状态内容均未删或修改。

initUndoable()方法,如果用keyPressed事件,那么最近的状态未加到undoManager.edits列里。因此选用keyReleased事件。如果监听valueChanged事件,那么代码就

和JAVA与模式一书中一样,只能实现最近一次的编辑撤消。

packageundoRedo;

importjava.awt.TextArea;

import java.awt.event.*;

importjava.util.Hashtable;

import javax.swing.undo.*;

importjavax.swing.undo.StateEditable;

public class UndoableTextArea extends TextArea implementsStateEditable {

privateUndoManager undoManager;

private final static String KEY_STATE="UndoableTextAreaKey";

privateStateEdit currentEdit;

boolean textChanged = false;

publicUndoableTextArea()

{

super();

initUndoable();

}

publicUndoableTextArea(String string)

{

super(string);

initUndoable();

}

//存储状态

public void storeState(HashtablehashTable) {

//TODO Auto-generated method stub

hashTable.put(KEY_STATE, this.getText());

}

//还原状态

public void restoreState(Hashtable, ?>hashTable) {

//TODO Auto-generated method stub

Object data =hashTable.get(KEY_STATE);

if(data!=null)

{

this.setText((String)data);

}

}

//撤销方法

public booleanundo()

{

try{

undoManager.undo();

System.out.println("undo=" +undoManager.toString());

return true;

}catch(CannotUndoException e)

{

System.out.println("Can't undo");

}

return false;

}

//重做方法

public booleanredo()

{

try{

undoManager.redo();

System.out.println("redo=" +undoManager.toString());

return true;

}catch(CannotRedoException e)

{

System.out.println("Can't redo");

}

return false;

}

private voidinitUndoable()

{

this.undoManager = newUndoManager();

this.currentEdit = new StateEdit(this);

this.addKeyListener(newKeyAdapter()

{

/**

* 如果用keyPressed事件,那么最近的状态未加到undoManager.edits列里。

* 因此选用keyReleased事件。

*

public void keyPressed(KeyEvent event)

{

if(event.isActionKey())

{

//takeSnapshot();

}else

{

textChanged = true;

takeSnapshot();

}

}

*/

public voidkeyReleased(KeyEvent event)

{

if(event.isActionKey())

{

//takeSnapshot();

}else{

textChanged = true;

takeSnapshot();

}

}

});

this.addFocusListener(newFocusAdapter()

{

public voidfocusLost(FocusEvent event)

{

//takeSnapshot();

}

});

}

private voidtakeSnapshot()

{

if(textChanged)

{

this.currentEdit.end();

this.undoManager.addEdit(this.currentEdit);

this.currentEdit = new StateEdit(this);

System.out.println("takeSnapshot=" +undoManager.toString());

textChanged = false;

}

}

}

Command抽象类:定义按钮,抽象方法 execute()

UndoCommand,RedoCommand均是Command类的实现,类似于命令模式中的具体按钮,调用接收者的方法进行实现。

packageundoRedo;

importjava.awt.Button;

public abstract class Command extendsButton {

publicCommand(String caption)

{

super(caption);

}

public abstract voidexecute();

}

packageundoRedo;

public class UndoCommand extendsCommand {

UndoableTextArea text;

publicUndoCommand(UndoableTextArea text)

{

super("Undo");

this.text =text;

}

@Override

public voidexecute() {

//TODO Auto-generated method stub

text.undo();

}

}

packageundoRedo;

public class RedoCommand extendsCommand {

UndoableTextArea text;

publicRedoCommand(UndoableTextArea text)

{

super("Redo");

this.text =text;

}

@Override

public voidexecute() {

//TODO Auto-generated method stub

text.redo();

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值