Niepewności dotyczące implementacji akcji i użycia jednego modelu z wieloma widokami

Jestem całkowitym nowicjuszem w zakresie programowania GUI i może mój problem ma całkiem proste rozwiązanie. Usiłuję zaimplementować interfejs GUI Java Swing, który służy jako edytor dla struktury danych typu drzewa. Interfejs GUI jest podzielony na trzy części:

Przeglądarka drzew w lewej ćwiartce okna wyświetla dane o strukturze drzewa.

Duży górny prawy obszar wyświetla edytory zawierające pola tekstowe, tabele i tym podobne. Każdy inny rodzaj obiektu w strukturze drzewa ma swój własny edytor, który jest wyświetlany po wybraniu go w przeglądarce drzewa.

W prawym dolnym obszarze wyświetlana jest przeglądarka konsoli. Służy do wyświetlania komunikatów o konkretnych działaniach.

Staram się ściśle przestrzegać ścisłego oddzielenia modelu od jego wizualizacji w przeglądarkach / edytorach drzew w moim programie. Dlatego stworzyłem instancję podklasy DefaultTreeModel (MyTreeModel), która przechowuje odwołania do danych biznesowych i instancję podklasy JTree, która zapewnia wizualną reprezentację struktury drzewa.

Próbuję zaimplementować funkcjonalność, która modyfikuje dane za pomocą klas Action. Każda akcja (jak CreateNode, RenameNode, DeleteNode) jest zaimplementowana w swojej własnej klasie akcji (podklasa AbstractAction). Akcje są używane w menu kontekstowym przeglądarki drzewa oraz w menu „Edycja” aplikacji. Ale chcę też ponownie wykorzystać niektóre z nich w częściach edytora GUI, np. akcja RenameNode. I tutaj utknąłem.

Przeglądarka drzewa wyświetla ikonę wraz z nazwą dla każdego węzła w drzewie. Odpowiedni edytor zawiera między innymi także pole JTextField, które pokazuje nazwę powiązanego węzła.

Wiem, że mogę dołączyć obiekty akcji do JMenu, JPopupMenu, a nawet do obiektów JTextField za pomocą metody setAction. Zrobiłem tak, a teraz mam wpis menue „Zmień nazwę” w menu „Edycja” programu, w menu podręcznym skojarzonym z JTree, które reprezentuje przeglądarkę drzewa, a pole JTextField pokazujące nazwę węzła ma również tę akcję.

Aby zmienić atrybut „Nazwa” węzła drzewa, utworzyłem klasę RenameNode jako podklasę AbstractAction. Jak już wspomniano, nazwa jest wyświetlana w każdym węźle w przeglądarce drzewa, a akcja po prostu czyni ten tekst edytowalnym. Ten kod wygląda następująco (w klasie RenameNode):

public void actionPerformed(ActionEvent ev) {
    // "mouseOverPath" is the Treepath were the mouse was placed on
    // when the popup menu was opened
    if (tree.existsMouseOverPath()) {
        tree.startEditingAtPath(tree.mouseOverPath);
    } else if (tree.getSelectionCount() != 0) {
        tree.startEditingAtPath(tree.getSelectionPath());
    }
}

Jeśli instrukcje są potrzebne do poprawnego działania z:

- menu podręczne (pierwsze jeśli instrukcja; tutaj obiekt znajdujący się pod myszą po otwarciu menu podręcznego jest edytowalny)

- menu aplikacji (drugie jeśli instrukcja; tutaj węzeł drzewa, który jest aktualnie wybrany - jeśli w ogóle - jest edytowalny).

Cóż, to działa dobrze, w zasadzie, ale w rzeczywistości zmiana nazwy węzła nie odbywa się za pomocą kodu w metodzie actionPerformed (ActionEvent ev) klasy RenameAction. Prawdziwa zmiana nazwy węzła jest wykonywana w klasie drzewa MyTreeModel w metodzie valueForPathChanged (), która jest zastępowana w następujący sposób:

public class MyTreeModel extends DefaultTreeModel {


[...]

    @Override
    public void valueForPathChanged(TreePath path, Object newValue) {
    final MyTreeNode aNode = (MyTreeNode)path.getLastPathComponent();
    if (newValue instanceof String) {
        ((MyNode) aNode.getUserObject()).setName((String) newValue);
    } else {
        aNode.setUserObject(newValue);
    }
        nodeChanged(aNode);
    }

[...]

}

Absolutnie nie mam pojęcia, jak właściwie można tu zastosować koncepcję działań. Jeszcze gorsza jest sytuacja z operacją zmiany nazwy podczas wykonywania zmiany tekstu w obiekcie JTextField. W tej chwili nie wiem, jak wdrożyć to w czysty sposób. JTextField powinien zostać skojarzony z pojedynczym węzłem ze struktury modelu drzewa, ponieważ jego model i dołączona akcja powinny zmodyfikować ten model, a gdy ten model zostanie zmieniony, przeglądarka drzewa musiałaby zostać powiadomiona, aby zaktualizować nazwę odpowiedniego węzła w przeglądarce drzewa.

Zakładam, że klasa MyNode (która jest podklasą DefaultMutableTreeNode) musiałaby zaimplementować interfejs Document, a klasa RenameAction musiałaby go zmodyfikować, a następnie wydać zdarzenie, aby powiadomić przeglądarkę drzewa, która wyświetla zmieniony węzeł.

Konkluzja: Muszę przyznać, że jeszcze nie do końca rozumiałem, jak poprawnie zaimplementować akcję, która ma być używana w wielu miejscach w GUI i nie rozumiem całkowicie, jak zaimplementować model, który może być używany przez wiele obiektów GUI (w moim przypadku JTree i JTextField). Prawdopodobnie wszystko to jest dość proste ...

Z góry dziękuję za wszelką pomoc!

Cóż, udzielone odpowiedzi były bardzo pomocne w wyjaśnieniu, w jaki sposób można używać akcji razem z JTrees. Ale jest jeszcze jeden punkt, który chciałbym omówić. W moim GUI mam drzewo reprezentujące moje dane biznesowe połączone z edytorami danych (drzewo znajdujące się w lewej ćwiartce okna i poza tym edytor specyficzny dla typu węzła). Wszystkie węzły mają nazwy, które można zmienić. Ponadto edytory zawierają pole tekstowe (zaimplementowane za pomocą JTextField), w którym wyświetlana jest nazwa węzła i która może być również edytowana. Moja niepewność jest tutaj następująca: Pole JTextField umożliwia przypisanie do niego obiektu akcji, a także modelu. W rzeczywistości model byłby obiektem węzłowym już oglądanym w JTree. Myślę, że powinien istnieć sposób użycia tego samego obiektu modelu używanego w JTree również jako modelu dla JTextField w edytorze, a także ponownego użycia klasy Action tam. Jeśli chodzi o ponowne użycie modelu, myślę, że moja klasa modelu MyTreeNode również będzie musiała zaimplementować interfejs Document, prawda? A gdy pojawił się edytor specyficzny dla węzła, musiałbym skojarzyć węzeł aktualnie wybrany w JTree z obiektem JTextField za pomocą metody setDocument (). Wreszcie moja RenameNodeAction musiałaby zmienić nazwę węzła JTextField. Tak więc moim głównym punktem jest: wyświetlenie jednego modelu w wielu widokach i ponowne użycie tylko jednej akcji RenameAction wszędzie tam, gdzie nazwa węzła ma zostać zmieniona. Czy to ma sens i czy mój pomysł, jak to osiągnąć, jest możliwy?

questionAnswers(3)

yourAnswerToTheQuestion