2012-07-17 1 views
10

XML 편집기를 만들었는데 마지막 단계에서 실행 취소/다시 실행 기능을 추가해야합니다.Java에서 액션에 대해 간단한 실행 취소/다시 실행을 구현하려면 어떻게해야합니까?

사용자가 요소, 속성 또는 텍스트를 JTree에 추가 할 때만 실행 취소/다시 실행을 추가해야합니다.

저는 아직 완전히 새롭지 만 학교에서는 오늘 두 가지 스택 객체 []를 생성하여 실행 취소 및 다시 실행을 시도하고 수행 된 동작을 추가하려고했습니다 (실패한 경우).

는 예를 들어, 내가 가진 :

Action AddElement() { 

// some code 
public void actionPerformed(ActionEvent e) { 

        performElementAction(); 
       } 
} 

performElementAction은 실제로 JTree에에 요소를 추가합니다.

실행 취소 스택에 수행 된이 동작을 추가하는 방법을 추가하고 싶습니다. 실행 취소 작업을 수행하는 간단한 방법이 있습니까?

악인처럼 소리 죄송합니다,하지만 그건 내가 무엇 :(

+0

내장 된 실행 취소 지원을 확인하십시오. 나는 그것을 사용한 적이 없으며 Swing 튜토리얼을 찾을 수는 없지만 [여기] (http://docs.oracle.com/javase/6/docs/api/javax/swing/undo/UndoManager.html)) 매니저입니다. –

답변

7

는, 그 용도가/다시 실행 기능을 취소 구현 포함 Command Pattern에서보세요이다.

0

나는 액션을 만들려고 할 것이다 AddElementAction 클래스가 Action을 상속받은 AddElementAction 클래스를 가지고있는 경우 AddElementAction은 Do() 및 Undo() 메서드를 사용하여 요소를 추가/제거 할 수 있으므로 실행 취소/다시 실행을위한 두 개의 스택 스택을 유지하고 Do()/Undo()를 팝업하기 전에 맨 위 요소에서 수행합니다.

+0

['javax.swing.undo.UndoManager'] (http://docs.oracle.com/javase/6/docs/api/javax/swing/undo/UndoManager.html) –

1

tutorial은 Swing에 대한 명령 패턴 및 실행 취소/다시 실행 메커니즘의 기본을 설명합니다. 희망이 도움이됩니다.

+0

그 기사는 정말 도움이됩니다. 감사. –

0

You have to define undo(), redo() operations along with execute() in Command interface itself.

예 :

interface Command { 

    void execute() ; 

    void undo() ; 

    void redo() ; 
} 

이 ConcreteCommand 클래스의 상태를 정의합니다. execute() 메소드 이후의 현재 상태에 따라 명령어를 실행 취소 스택 또는 재실행 스택에 추가할지 여부를 결정하고 그에 따라 결정해야합니다.

더 나은 이해를 위해이 undo-redo 명령 기사를 살펴보십시오.

2

TL : 명령 및 메멘토 패턴 (Design Patterns - Gama et. al)을 구현하여 실행 취소 및 다시 실행 작업을 지원할 수 있습니다.

메멘토 패턴

이 간단한 패턴은 객체의 상태를 저장할 수 있습니다. 새 클래스에 객체를 간단히 감싸고 상태가 변경 될 때마다 객체를 업데이트하십시오.

public class Memento 
{ 
    MyObject myObject; 

    public MyObject getState() 
    { 
     return myObject; 
    } 

    public void setState(MyObject myObject) 
    { 
     this.myObject = myObject; 
    } 
} 

명령 패턴

명령 패턴은 우리가 실행 취소의 경우에 필요한 유품 객체 (우리는 실행 취소/다시 실행을 지원하려는) 원의 객체를 저장합니다.

  1. 실행 : 또한, 2 가지 방법은 정의 된 명령어
  2. unExecute을 실행한다 : 명령을 제거

번호 :

public abstract class Command 
{ 
    MyObject myObject; 
    Memento memento; 

    public abstract void execute(); 

    public abstract void unExecute(); 
} 

은 "논리적 정의 명령 (예 : 삽입)을 확장하는 "동작":

public class InsertCharacterCommand extends Command 
{ 
    //members.. 

    public InsertCharacterCommand() 
    { 
     //instantiate 
    } 

    @Override public void execute() 
    { 
     //create Memento before executing 
     //set new state 
    } 

    @Override public void unExecute() 
    { 
     this.myObject = memento.getState()l 
    } 
} 

적용 패턴 :

이 마지막 단계는 실행 취소/다시 실행 동작을 정의합니다. 핵심 아이디어는 명령의 히스토리 목록으로 작동하는 명령 스택을 저장하는 것입니다. 다시 실행을 지원하기 위해 실행 취소 명령이 적용될 때마다 보조 포인터를 유지할 수 있습니다. 새 객체가 삽입 될 때마다 현재 위치 이후의 모든 명령이 제거됩니다. 그는 deleteElementsAfterPointer 방법에 의해 달성있어 아래 정의 :

private int undoRedoPointer = -1; 
private Stack<Command> commandStack = new Stack<>(); 

private void insertCommand() 
{ 
    deleteElementsAfterPointer(undoRedoPointer); 
    Command command = 
      new InsertCharacterCommand(); 
    command.execute(); 
    commandStack.push(command); 
    undoRedoPointer++; 
} 

private void deleteElementsAfterPointer(int undoRedoPointer) 
{ 
    if(commandStack.size()<1)return; 
    for(int i = commandStack.size()-1; i > undoRedoPointer; i--) 
    { 
     commandStack.remove(i); 
    } 
} 

private void undo() 
{ 
    Command command = commandStack.get(undoRedoPointer); 
    command.unExecute(); 
    undoRedoPointer--; 
} 

private void redo() 
{ 
    if(undoRedoPointer == commandStack.size() - 1) 
     return; 
    undoRedoPointer++; 
    Command command = commandStack.get(undoRedoPointer); 
    command.execute(); 
} 

결론 :이 디자인은 강력하게 만드는 무엇

당신이 원하는대로합니다 (Command 클래스를 확장하여) 많은 명령을 추가 할 수 있다는 사실이다 예를 들어, , RemoveCommand, UpdateCommand 등등. 또한 동일한 패턴을 모든 유형의 객체에 적용 할 수 있으므로 재사용 가능은 서로 다른 사용 사례에 따라으로 수정 가능합니다.

+0

실행 취소/다시 실행 단계의 수를 제한하는 방법은 무엇입니까? 스택의 크기를 조정할 수는 없습니다. – Atlas2k

+0

@ Atlas2k를 사용하면 임계 값 (예 :'int threshhold = 30')을 가질 수 있으며 현재 스택 크기를 기반으로 모든 "이전"명령을 제거 할 수 있습니다. 예를 들어'insertCommand()'를 호출하고'commandStack.size()'가 30보다 큰 경우 첫 번째 요소를 제거합니다 ('commandStack.remove (0)'). 주요 아이디어는 스택을 특정 임계 값 크기로 제한하는 것입니다. 네, 더 복잡한 유스 케이스지만, 확실히 할 수 있습니다. –

+0

나는 이것을 사용하여 최대 스택 크기를 설정했습니다 : http://ntsblog.homedev.com.au/index.php/2010/05/06/c-stack- 최대 - 제한 / – Atlas2k

관련 문제