2012-07-17 31 views
10

Tôi đã tạo một trình soạn thảo XML và tôi bị kẹt ở giai đoạn cuối: thêm chức năng hoàn tác/làm lại.Làm cách nào để triển khai hoàn tác đơn giản/làm lại cho các hành động trong java?

Tôi chỉ phải thêm hoàn tác/làm lại khi người dùng thêm phần tử, thuộc tính hoặc văn bản vào JTree.

Tôi vẫn còn khá mới ở đây nhưng trong trường hôm nay tôi đã cố gắng (không thành công) để tạo hai đối tượng ngăn xếp [] được gọi là hoàn tác và làm lại và thêm các hành động được thực hiện vào chúng.

Ví dụ, tôi có:

Action AddElement() { 

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

        performElementAction(); 
       } 
} 

các performElementAction chỉ thực sự thêm một phần tử vào JTree.

Tôi muốn thêm một cách để thêm hành động này được thực hiện vào hoàn tác hoàn tác của tôi. có cách nào đơn giản để chỉ undo.push (toàn bộ hành động được thực hiện) hay gì đó không?

Xin lỗi vì nghe có vẻ giống như một phản diện, nhưng đó là những gì tôi :(

+0

Hãy nhớ xem xét hỗ trợ hoàn tác được tích hợp sẵn; Tôi đã không bao giờ sử dụng nó và tôi không thể tìm thấy một hướng dẫn Swing cho nó, nhưng [ở đây] (http://docs.oracle.com/javase/6/docs/api/javax/swing/undo/UndoManager.html) là người quản lý. –

Trả lời

7

Hãy nhìn vào các Command Pattern, sử dụng của nó bao gồm việc thực hiện undo/redo chức năng.

0

tôi sẽ cố gắng để tạo ra một hành động class, với một lớp AddElementAction kế thừa hành động AddElementAction có thể có phương thức Do() và Undo() để thêm/xóa các phần tử tương ứng. Sau đó, bạn có thể giữ hai ngăn tác vụ để hoàn tác/làm lại và chỉ cần gọi Do()/Hoàn tác() trên phần tử trên cùng trước khi xuất hiện.

+0

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

1

Điều này tutorial giải thích cơ bản của Command Pattern và cơ chế undo/redo cho Swing. Hy vọng nó giúp.

+0

Bài viết đó thực sự hữu ích. Cảm ơn. –

0

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

dụ:

interface Command { 

    void execute() ; 

    void undo() ; 

    void redo() ; 
} 

Xác định một Nhà nước trong lớp ConcreteCommand của bạn. Tùy thuộc vào trạng thái hiện tại sau phương thức execute(), bạn phải quyết định có nên thêm lệnh vào Undo Stack hay Redo Stack và đưa ra quyết định tương ứng hay không.

Hãy xem bài viết này undo-redo để hiểu rõ hơn.

2

TL; DR: Bạn có thể hỗ trợ hoàn tác và thực hiện lại các tác vụ bằng cách triển khai mẫu Command and Memento (Design Patterns - Gama et. al).

Các Memento Pattern

mô hình đơn giản này cho phép bạn lưu các bang của một đối tượng. Đơn giản chỉ cần bọc đối tượng trong một lớp mới và bất cứ khi nào trạng thái của nó thay đổi, hãy cập nhật nó.

public class Memento 
{ 
    MyObject myObject; 

    public MyObject getState() 
    { 
     return myObject; 
    } 

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

Các mẫu lệnh

Các mẫu Command lưu trữ các đối tượng gốc (mà chúng tôi muốn hỗ trợ undo/redo) và đối tượng vật lưu niệm, mà chúng ta cần trong trường hợp lùi lại.Hơn nữa, 2 phương pháp được định nghĩa:

  1. thực hiện: thực hiện lệnh
  2. unExecute: loại bỏ các lệnh

Code:

public abstract class Command 
{ 
    MyObject myObject; 
    Memento memento; 

    public abstract void execute(); 

    public abstract void unExecute(); 
} 

Các định nghĩa logic " Tác vụ "mở rộng Lệnh (ví dụ: Chèn):

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 
    } 
} 

Áp dụng các mô hình:

bước cuối cùng này quy định các hành vi undo/redo. Ý tưởng cốt lõi của họ là lưu trữ một loạt các lệnh hoạt động như một danh sách lịch sử của các lệnh. Để hỗ trợ làm lại, bạn có thể giữ một con trỏ thứ hai bất cứ khi nào lệnh hoàn tác được áp dụng. Lưu ý rằng bất cứ khi nào một đối tượng mới được chèn vào, thì tất cả các lệnh sau khi vị trí hiện tại của nó được loại bỏ; đó là đạt được bằng phương pháp deleteElementsAfterPointer định nghĩa dưới đây:

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

Kết luận:

Điều gì làm cho thiết kế này mạnh mẽ là một thực tế mà bạn có thể thêm bao nhiêu lệnh như bạn muốn (bằng cách mở rộng các lớp Command) ví dụ , RemoveCommand, UpdateCommand và cứ tiếp tục như vậy. Hơn nữa, cùng một mẫu được áp dụng cho bất kỳ loại đối tượng nào, làm cho thiết kế có thể sử dụng lạicó thể sửa đổi trong các trường hợp sử dụng khác nhau.

+0

Bạn sẽ giới hạn số bước hoàn tác/làm lại như thế nào? Nó không thể kích thước một ngăn xếp. – Atlas2k

+0

@ Atlas2k bạn có thể có ngưỡng (ví dụ: 'int threshhold = 30') và sau đó xóa tất cả các lệnh" cũ hơn "dựa trên kích thước ngăn xếp hiện tại. Ví dụ, nếu bạn gọi 'insertCommand()' và 'commandStack.size()' của bạn lớn hơn 30, thì bạn loại bỏ phần tử đầu tiên ('commandStack.remove (0)'). Ý tưởng chính là để hạn chế ngăn xếp của bạn đến một kích thước ngưỡng nhất định. Có, trường hợp sử dụng phức tạp hơn, nhưng chắc chắn có thể làm được :) –

+0

Tôi đã làm theo cách này để đặt kích thước ngăn xếp tối đa của mình: http://ntsblog.homedev.com.au/index.php/2010/05/06/c-stack- với giới hạn tối đa / – Atlas2k

Các vấn đề liên quan