Java 中的可撤消文本区域

Undoable Text Area in Java

我刚刚开始学习 java 中的编程...我想创建一个小型文本编辑器(Windows 记事本克隆...)。

我正在寻找 Class 扩展 JTextArea 实现撤消和重做操作。我找到了符合我需要的代码,并尝试根据我的目的对其进行调整。

代码如下:

import java.awt.Toolkit;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JTextArea;
import javax.swing.event.UndoableEditEvent;
import javax.swing.event.UndoableEditListener;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.UndoManager;

class UndoableTextArea extends JTextArea implements UndoableEditListener, FocusListener, KeyListener 

{

    private static final long serialVersionUID = 1L;
    private UndoManager m_undoManager;

    public UndoableTextArea() {
        this(new String());
    }

    public UndoableTextArea(String text) {
        super(text);
        getDocument().addUndoableEditListener(this);
        this.addKeyListener(this);
        this.addFocusListener(this);
    }

    private void createUndoMananger() {
        m_undoManager = new UndoManager();
        m_undoManager.setLimit(50);
    }

    private void removeUndoMananger() {
        m_undoManager.end();
    }

    public void focusGained(FocusEvent fe) {
        createUndoMananger();
    }

    public void focusLost(FocusEvent fe) {
        removeUndoMananger();
    }

    public void undo()
    {
          try {
                m_undoManager.undo();
              } catch (CannotUndoException cue) {
                Toolkit.getDefaultToolkit().beep();
              }
    }

    public void redo()
    {
          try {
                m_undoManager.redo();
              } catch (CannotRedoException cue) {
                Toolkit.getDefaultToolkit().beep();
              }
    }

    public void undoableEditHappened(UndoableEditEvent e) {
        m_undoManager.addEdit(e.getEdit());
    }

    public void keyPressed(KeyEvent e) {
    if ((e.getKeyCode() == KeyEvent.VK_Z) && (e.isControlDown())) {
      try {
        m_undoManager.undo();
      } catch (CannotUndoException cue) {
        Toolkit.getDefaultToolkit().beep();
      }
    }

    if ((e.getKeyCode() == KeyEvent.VK_Y) && (e.isControlDown())) {
      try {
        m_undoManager.redo();
      } catch (CannotRedoException cue) {
        Toolkit.getDefaultToolkit().beep();
      }
    }
    }

    public void keyReleased(KeyEvent e) {
    }

    public void keyTyped(KeyEvent e) {
    }
}

使用加速键 CTRL+Z,CTRL+Y 在输入对象时没有问题....但是我添加的方法 undo()redo() 用于使用 menuItem objetcs 中的此操作,不起作用...

(...)       
menuItem15 = new JMenuItem("Undo");
menuItem16 = new JMenuItem("Redo");
(...)



public void actionPerformed(ActionEvent e)
{

//Undo
if (e.getSource() == menuItem15)
{
    textArea1.undo();
}


//Redo
if (e.getSource() == menuItem16)
{
    textArea1.redo();
}
}

有什么建议吗? 抱歉我的英语不好...

谢谢!

问题可能是由于代码在 focusGained 和 focusLost 事件上添加和删除 UndoManager 造成的:

public void focusGained(FocusEvent fe) {
    createUndoMananger();
}

public void focusLost(FocusEvent fe) {
    removeUndoMananger();
}

当你点击菜单时,文本区域暂时失去焦点,UndoManager被丢弃,然后创建一个新的实例。新实例不知道以前的可撤消编辑事件,因此撤消和重做不起作用。

我建议创建一次 UndoManager 并将其附加到文档,直到 GUI 被处理(即直到对话框/window 关闭)。

已解决! 我意识到 UndoManager 的创建与我的 JTextArea 扩展对象的 focusGained() 事件相关联。因此,当我通过 menuItem 选择操作时,我失去了焦点并且 UndoManager 被销毁了。

我将方法 createUndoMananger 从私有更改为 public,并在 class...

外部调用
(..)
public void createUndoMananger() {
    m_undoManager = new UndoManager();
    m_undoManager.setLimit(50);
}

public void removeUndoMananger() {
    m_undoManager.end();
}

public void focusGained(FocusEvent fe) {
    //createUndoMananger();
    //System.out.println("focusGained()");
}

public void focusLost(FocusEvent fe) {
    //removeUndoMananger();
    //System.out.println("focusLost()");
}

(...)

还是谢谢!!!