2016-12-01 82 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()"); 
} 

(...)

還是要謝謝你!