2015-06-15 20 views
10

Niedawno zacząłem uczyć się API JavaFX, po tym, jak już przeżyłem Swing.Dlaczego JavaFX nie zawiera operacji cofania?

Zauważyłem, że nawet wiele zajęć zostało już dobrze wdrożonych w AWT i Swing, zostały one skutecznie ponownie wprowadzone w JavaFX. Obejmuje to:

javafx.scene.paint.Color 
javafx.event.ActionEvent 

vs.

java.awt.Color 
java.awt.event.ActionEvent 

i znacznie więcej, choć może to już łatwo wymagają korzystania im. Zakładam, że jest to:

  • Usuń JavaFX z innych bibliotek (aby nowi deweloperzy nie wiedzieli o ich istnieniu ..., OK).
  • Wykorzystaj wyrażenia lambda w języku Java 8.
  • Skorzystaj z generycznych typów Java i typów wyliczeniowych.
  • Projektowanie z myślą o FXML.
  • Powiązania ... Wersja magii JavaFX.

Jeśli moje założenia są prawdziwe, dlaczego nie obejmują one nową implementację:

javax.swing.undo 

pakietu?

Chociaż rozumiem, że cofnięcie nie ma nic wspólnego z interfejsem użytkownika, więc nie ma też nic wspólnego z Swingiem. Jeśli z jakiegokolwiek powodu zdecydowali się umieścić go w pakiecie javax.swing, mogliby dołączyć go do JavaFX.

+0

To interesujące pytanie. Wielu użytkowników usiłuje twierdzić, że cofanie/ponawianie ma wiele wspólnego z interfejsami użytkownika, ponieważ użytkownik jest znacznie bardziej wygodny w odkrywaniu interfejsu użytkownika, wiedząc, że może odwrócić każdą funkcję, która okazuje się niemile widziana. A czytanie dokumentów dla javax.swing.undo daje jasno do zrozumienia, że ​​sama implementacja jest daleka od trywialności. – VGR

+3

Możesz chcieć zapytać o listę dyskusyjną [openjfx-dev] (http://mail.openjdk.java.net/mailman/listinfo/openjfx-dev). [UndoFX] (https://github.com/TomasMikula/UndoFX) to trzecia strona open source framework do cofania stworzona do użycia z JavaFX. UndoFX jest używany w [RichTextFX] (https://github.com/TomasMikula/RichTextFX), edytorze tekstu opartym na JavaFX. – jewelsea

+0

@jewelsea - dlaczego nie umiesz podać odpowiedzi ?! – Deian

Odpowiedz

5

Dlaczego "zapomnieli" wprowadzić to w życie, to dobre pytanie. Twierdzę, że JavaFX jest nadal w fazie rozwoju (powinno to powiedzieć wszystko). Jednak potrzebowałem tego dawno temu i zaimplementowałem własne podejście przy użyciu wzorca poleceń. Jak pokazano poniżej, nie wymaga to wiele wysiłku i jest bardzo proste.

Najpierw należy utworzyć interfejs o nazwie Command, aby wykonać niektóre operacje w aplikacji.

public interface Command { 
    /** 
    * This is called to execute the command from implementing class. 
    */ 
    public abstract void execute(); 

    /** 
    * This is called to undo last command. 
    */ 
    public abstract void undo(); 
} 

Następnie trzeba będzie jakąś klasę o nazwie Historia aby zapisać wykonane polecenia i je cofnąć.

public final class History { 
    // ... 
    private static History instance = null; 
    private final Stack<Command> undoStack = new Stack<Command>(); 
    // ... 

    public void execute(final Command cmd) { 
     undoStack.push(cmd); 
     cmd.execute(); 
    } 

    public void undo() { 
     if (!undoStack.isEmpty()) { 
      Command cmd = undoStack.pop(); 
      cmd.undo(); 
     } else { 
      System.out.println("Nothing to undo."); 
     } 
    } 

    public static History getInstance() { 
     if (History.instance == null) { 
      synchronized (History.class) { 
       if (History.instance == null) { 
        History.instance = new History(); 
       } 
      } 
     } 
     return History.instance; 
    } 

    private History() { } 
} 

W FXML należy utworzyć przycisk dla GUI, który powinien wywołać funkcję cofania aplikacji. W FXML utwórz przycisk, taki jak następujący:

<Button fx:id="btnUndo" font="$x2" onAction="#onUndo" prefWidth="75.0" 
     text="Undo" textAlignment="CENTER" underline="false"> 
    <tooltip> 
     <Tooltip text="Undo last command" textAlignment="JUSTIFY" /> 
    </tooltip> 
    <HBox.margin> 
     <Insets left="5.0" right="5.0" fx:id="x1" /> 
    </HBox.margin> 
</Button> 

W swojej klasie kontrolera odwołujesz się do przycisku z FXML.

public class Controller { 
    // ... 
    @FXML private Button btnUndo; 
    // ... 

    @FXML 
    public void onUndo(ActionEvent event) 
    { 
     History.getInstance().undo(); 
    } 
} 

Jak widać, najlepszą rzeczą jest to, że Historia klasa jest Singleton. Dzięki temu możesz uzyskać dostęp do zajęć z dowolnego miejsca.

Dziedzicz z Komenda Interfejs do wdrożenia nowego polecenia. Użyj niektórych przycisków lub podobnych elementów GUI dla nowych funkcji i wykonaj polecenie niestandardowe, używając historii.

// You can give arguments to command constructor if you like 
Command someCmd = new SomeCommand(); 
History.getInstance().execute(someCmd); // Saved to history; now you're able to undo using button 

Dzięki temu podejściu będzie można cofnąć operację. Możliwe jest również zaimplementowanie niektórych funkcji ponownego wykonywania. W tym celu wystarczy dodać przycisk powtórzenia w FXML i odpowiednią metodę w interfejsie Historia i Command.

Aby uzyskać więcej informacji na temat wzorca polecenia, spójrz na here.

Happy Coding!

+0

Ładne rozwiązanie, ale technicznie 'javax.swing.undo' nadal ma zastosowanie do JavaFX. Wolałbym się do tego trzymać, ponieważ jest bardziej wytrzymały. Nadal oczekuję specjalnej implementacji dla JavaFX - jako UndoFX - w oficjalnej wersji. – Mordechai

+0

Tak, to wygląda na fajne rozwiązanie ... ale dlaczego właściwie nie użyłeś istniejącego pakietu 'swing.undo'? Pakiety Swing są nadal pakowane w Javę, więc czy nie jest to klasyczny przypadek ponownego wynalezienia koła? Czy masz inne uzasadnienie? –