JTree

BlubBlub

Bekanntes Mitglied
Hi,
ich wollte einen JTree erstellen und mit Daten füllen.
Der übersichtlichkeithalber wollte ich das erstellen der ganzen Knoten
in einer anderen Klasse auslagern.
Also dachte ich mir ich schreibe Code wie den der unter "Mein Vorgehen" zu sehen ist.
Das Problem ist allerdings, dass das nicht funktioniert.
Wenn man das Standardvorgehen wählt, dann muss man
JTree tree = new JTree(rootNode);
also man übergibt im Konstruktor den rootNode. Anschließend kann man den Tree einfach in
ein Panel oder JFrame einbetten.
Bei meinem Code weiß ich aber nicht was ich mit den rootNode machen soll nachdem ich ihn
fertig erstellt habe mit allen Unterknoten. Ein add(rootNode) geht nicht. Und super() kann ich auch
nicht einfach den rootNode übergebe, da super() gleich zu beginn aufgerufen werden muss und ich
da logischerweise meinen rootNode noch nicht erstellt habe.
Was muss ich korigieren damit mein Baum korrekt angezeigt wird?

Standard:
Java:
DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode("Fields");
rootNode.add(...);
JTree tree = new JTree(rootNode);
JScrollPane treeScrollPane = new JScrollPane(tree);
add(treeScrollPane);


Mein Vorgehen:
Java:
public class MyTree extends JTree
{
           super();
           DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode("Fields");
           rootNode.add(...);

           add(rootNode); // Nicht erlaubt
}

MyTree tree = new MyTree();
JScrollPane treeScrollPane = new JScrollPane(tree);
add(treeScrollPane);
 
Setz ein neues Model mit deinem neuen Root:

Java:
JTree tree = ...
TreeNode rootNode = ...
tree.setModel( new DefaultTreeModel( rootNode ));
 
Das versteh ich noch nicht so ganz.
Meine momentane Ausgangslage ist:

Java:
public class MyTree extends JTree
{
           super();
           DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode("Fields");
           rootNode.add(...);
 
           add(rootNode); // Nicht erlaubt
}
 
MyTree tree = new MyTree();
JScrollPane treeScrollPane = new JScrollPane(tree);
add(treeScrollPane);
Ich hab in dieser Klasse meine recht komplizierte Baumstruktur erstellt.


Und nun soll ich also sowas machen:
Java:
JTree tree = ...
TreeNode rootNode = ...
tree.setModel( new DefaultTreeModel( rootNode ));

Ich versteh nicht ganz wo da jetzt meine Klasse MyTree() sein soll.
Weil das was du ja schreibst unterscheidet sich kaum vom Standardverfahren, welches ich
oben gezeigt habe.
Sowohl bei dem Standarvorgehen als auch bei deinem muss ich erst den rootNode komplett fertig erstellen.
Bei deinem Vorschlag müsste ich also auch einen ellenlangen Code zwischen
JTree tree = ... und tree.setModel(new DefaultTreeModel(rootNode)) erstellen bei dem mir der rootNode erstellt wird. Meine Absicht ist es aber nun diesen ellenlangen Code zu kapseln um die Übersicht zu erhalten und Änderung später leicher vornehmen zu können.

Ich wüßte schon ne alternative Lösung indem ich eine Klasse erstelle die eine statische Methode anbietet welche mir den rootPane mit allen seinen Unterknoten erzeugt und zurückgibt. Dann könnte ich es so lösen:
Java:
public class MyRootNodeCreator() 
{
             public MyRootNodeCreator()
             {
             }

             public static DefaultMutableTreeNode create()
             {
                      DefaultMutableTree rootNode = new DefaultMutableTreeNode();
                      rootNode.add(...) 
                       //Ellenlange komplizierte Baumstruktur

                      return rootNode;
             }
}

DefaultMutableTreeNode rootNode = MyRootNodeCreater.create();
JTree tree = new JTree(rootNode);
JScrollPane treeScrollPane = new JScrollPane(tree);
add(treeScrollPane);
Nur dachte ich ich könnte direkt einen fertigen Baum erstellen den ich einfach nur noch in
ein JFrame oder JPanel integrieren kann.

Vielleicht sagst du mir das richtige, aber so ganz kann ich dem grad noch nicht folgen.
 
Grundsätzliche Frage: Deine Klasse erbt von JTree. Aber erweitert Deine Klasse tatsächlich JTree bzw. warum erbst sie?

Üblicherweise gibt man einer Klasse auch einen "echten" Konstruktor.
Verwende ein TreeModel z.B. das vorgeschlagene DefaultTreeModel, das kann man jederzeit setzen - auch im Konstruktor nach einem super Aufruf.
 
Sorry, ich war etwas kryptisch.

Dein "MyTree" ist ein "JTree", also hat dein MyTree auch die Methode "setModel" (Vererbung: alles was die Superklasse hat, hat auch die Subklasse). Du kannst also aus deinem Konstruktor aus "setModel" aufrufen.
Java:
public class MyTree extends JTree{
     public MyTree(){
           super();
           DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode("Fields");
           rootNode.add(...);
 
           // add(rootNode); // Nicht erlaubt
           setModel( new DefaultTreeModel( rootNode ));
    }
}

Was das kapseln angeht, das ist natürlich eine gute Idee. Du kannst aus dem Konstruktor jederzeit ein paar Methoden aufrufen, die müssen auch nicht statisch sein. Vielleicht wäre es ganz gut, pro Knoten eine Methode zu haben, also irgendwie sowas:
Java:
public class MyTree extends JTree{
     public MyTree(){
           super();
           DefaultMutableTreeNode rootNode = createRoot();
 
           // add(rootNode); // Nicht erlaubt
           setModel( new DefaultTreeModel( rootNode ));
    }

    private DefaultMutableTreeNode createRoot(){
        DefaultMutabelTreeNode root = new DefaultMutabelTreeNode("Fields");
        root.add( createFieldA() );
        root.add( createFieldB() );
        return root;
    }

    private DefaultMutableTreeNode createFieldA(){
        DefaultMutabelTreeNode node = new DefaultMutabelTreeNode("A");
        node.add( nochEinKnoten() );
        return node;
    }

    private DefaultMutableTreeNode createFieldB(){
        DefaultMutabelTreeNode node = new DefaultMutabelTreeNode("A");
        return node;
    }

    ... // und noch viele weitere Methoden
}

Eine andere Idee: mach für jeden Knoten eine Klasse. Also eine Klasse "RootNode", "FieldNodeA", "FieldNodeB"... oder was immer du haben willst.
Java:
public class RootNode extends DefaultMutableTreeNode{
   public RootNode(){
      super( "Fields" );
      add( new FieldNodeA() );
      add( new FieldNodeB() );
      add( ... ); // noch mehr Knoten
   }
}

Und zum Schluss muss ich noch sagen, dass Michaels Frage berechtigt ist. Hat dein MyTree irgendeine Besonderheit die JTree nicht hat? In vielen Fällen wird ein Program übersichtlicher, wenn man auf Vererbung sparsam einsetzt.
 
Okay danke für die Antwort =)

Und zum Schluss muss ich noch sagen, dass Michaels Frage berechtigt ist. Hat dein MyTree irgendeine Besonderheit die JTree nicht hat? In vielen Fällen wird ein Program übersichtlicher, wenn man auf Vererbung sparsam einsetzt.

Nee hat es nicht. Aber ich erstelle eine komplexen Editor und da hab ich drei Bereiche. Einen MainPanel(JPanel), dann ein JTree und ein PropertPane (JPanel). Und um das Programm ein wenig zu struktuieren und die Übersicht zu behalten, sowie Änderungen später leicht vornehmen zu können, wollte ich eine eigene Klasse für JTree verwenden in der gleichzeitig die Knoten drin erstellt werden.
Das Programm wird nämlich mehrere tausend Zeilen Code habe, das ist der einzige Grund weshalb ich eine Klasse von JTree ableite die keine besonderen Zusätze hat.
 
Klassen bzw. die daraus erzeugten Objekte können auch einen JTree "besitzen".

Das versteh ich nicht ganz. Was meinst du damit? Welcher Grund oder welche Gründer sprechen in diesem Fall dagegen eine von JTree abgeleitete eigene Klasse zu verwenden?
 
Ohne den ganzen Thread gelesen zu haben, nur zur letzten Frage: Man sollte eher defensiv sein, was Vererbung angeht. Also nicht willkürlich von irgendwelchen Klassen erben, ohne, dass dafür ein driftiger Grund besteht. (Das wird manchmal auch als Merksatz "Favor Composition over Inheritance" zusammengefasst).

Insbesondere, wenn man selbst keine besondere Funktionalität hinzufügt, besteht kein Grund, zu erben. Als plakatives Beispiel:
Java:
class MyTree extends JTree
{
    public MyTree() {
        setFoo(...); // Lauter Aufrufe
        setBar(...); // von Methoden
        doThis(...); // die sowieso
        doThat(...); // 'public' sind
    }
}
so eine Klasse macht i.a. keinen Sinn. Genausowenig wie man eine Klasse schreiben würde wie
Java:
class ArrayListWith123 extends ArrayList 
{
    public ArrayListWith123()
    {
        add(1);
        add(2);
        add(3);
    }
}
😀

Aber nochmal: Das nur, ohne den Thread gelesen zu haben, und damit ohne den Zusammenhang zu kennen. Vielleicht macht das Erben bei dir auch Sinn.
 
Alles klar danke. Aber ich denke dennoch dass es in diesem Fall durchaus berechtigt ist von JTree abzuleiten, ohne die Klasse zu erweitern um die Übersicht zu bewahren und um den Code nur an einer zentralen Stelle ändern zu müssen. Zumindest in meinem Falle wo ich viel Code verwende.

Falls der einzige Grund der dagegen sprechen sollt nur lautet:
"Favor Composition over Inheritance"
Denn wenn die Funktionalität weiterhin gleich bleibt und sich nichts verändert, ist der Satz meines Achtens eher eine Richtlinie als eine zwingend zu befolgende Regelung. Man muss halt beim jeweiligen Fall abwägen.
 
Zuletzt bearbeitet:

Neue Themen


Zurück
Oben