2016-12-01 83 views
0

我刚刚接近java编程....我想创建一个小文本编辑器(Windows记事本克隆...)。Java中的可撤消文本区域

我正在寻找一个扩展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) { 
    } 
} 

使用Accellerators重点CTRL +žCTRL +Ÿ在对象打字,没有任何问题....但方法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(); 
} 
} 

有什么建议吗? 对不起,我的英语不好...

谢谢!

+1

尝试使用等于比较您的菜单项而不是==。 – duffymo

+1

否:他应该更进一步,每个按钮使用一个动作侦听器。或者更好:使用动作。 –

+0

里面的“actionPerformed”功能?我不相信...还有另外14个与菜单项相关的操作。 –

回答

2

的问题可能是由于该代码添加并在focusGained和focusLost事件取出的UndoManager:

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

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

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

我建议创建UndoManager一次,并保持它连接到文档直到GUI被放置(即直到对话框/窗口关闭)。

+1

是的!!!我也意识到了!非常感谢!!!! –

1

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

我改变了方法createUndoMananger从私人到公共,类外调用...

(..) 
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()"); 
} 

(...)

还是要谢谢你!