Eigenes TreeModel in JTree
-
Hallo zusammen,
gleich vorweg: Ich habe noch realtiv wenig Erfahrung mit Java, aber schon einiges mit C++ gemacht und somit auch etwas Erfahrung in OOP.
Jetzt wollte ich mal ein etwas aufwändigeres Projekt, nämlich eine Songtext-Verwaltung, in Java (Version 5 in eclipse 3.1) realisieren und habe die Daten hierarchisch als Baum geordnet um sie hinterher relativ einfach mit DOM in XML speichern zu können. Dazu habe ich mir ein eigenes TreeModel geschrieben und stehe jetzt vor dem Problem, dass das TreeModel in einem JTree dargestellt werden soll. Ich habe mich natürlich schon mithilfe von Google informiert, doch die Beispiele, die ich da gefunden habe helfen mir nur eingeschränkt weiter. Besonders die Arbeit mit den Listener-Klassen bereitet mir Schwierigkeiten. Am besten zeig ich euch mal ein bisschen Code:
//hier die Model-Klasse: import java.util.Vector; import javax.swing.event.TreeModelEvent; import javax.swing.event.TreeModelListener; import javax.swing.tree.TreeModel; import javax.swing.tree.TreePath; public class SongsTreeModel implements TreeModel { public SongRoot Root = null; private Vector<TreeModelListener> treeModelListeners = new Vector<TreeModelListener>(); SongsTreeModel(SongRoot VRoot){ Root = VRoot; } //... public boolean isLeaf(Object arg0) { return ((SongNode)arg0).isLeaf(); } public void valueForPathChanged(TreePath arg0, Object arg1) { // TODO Auto-generated method stub } public SongNode insertNodeInto(SongNode newChild, SongNode parent){ if(isRoot(parent)){ //Artist wird eingefügt ((SongRoot)parent).addArtist((Artist)newChild); nodesWereInserted(true, newChild); } if(!isLeaf(parent)){ //Song wird eingefügt ((Artist)parent).addSong((Song)newChild); nodesWereInserted(false, newChild); } return newChild; } public void nodesWereInserted(boolean isArtist, SongNode child) { Object arg0 = isArtist ? Root : ((Song)child).getArtist(); //Wenn ein Artist eingefügt wird, dann in Root, ansonsten zum Artist Object[] arg1a = {Root, child}; //Wenn Artist eingefügt Object[] arg1b = {Root, ((Song)child).getArtist(), child}; //Wenn Song eingefügt Object[] arg1 = isArtist ? arg1a : arg1b; for(int i = 0; i < treeModelListeners.size(); i++){ treeModelListeners.elementAt(i).treeNodesInserted(new TreeModelEvent(arg0, arg1)); //Event an Listeners } } public int getIndexOfChild(Object arg0, Object arg1) { return ((SongNode)arg0).getIndexOfChild((SongNode)arg1); } public void addTreeModelListener(TreeModelListener l) { treeModelListeners.addElement(l); } public void removeTreeModelListener(TreeModelListener l) { treeModelListeners.removeElement(l); } } //Die entscheidenden Zeilen aus der Test.java (der Hauptklasse): public class Test extends JFrame { //... private JTree jTree = null; private SongsTreeModel Model = null; //... private JTree getJTree() { if (jTree == null) { jTree = new JTree(getModel()); } return jTree; } private SongsTreeModel getModel() { if(Model == null) { Model = new SongsTreeModel(new SongRoot("Songs")); } return Model; }
Songs werden in dei Liste wie folgt eingefügt:
getModel().insertNodeInto(new Song(art, getTitleEdit().getText(), getAlbumEdit().getText(), new Integer(getTrackEdit().getText()), ""), art);
Dabei ist art der Knoten des Künstlers, der vorher bestimmt und auf ähnliche Art und Weise eingefügt wird.
Der Künstler wird über die Klasse Artist und der Song über die KLasse Song beschrieben, beide erben von SongNode, unterschieden werden sie über die Methode isLeaf(), bei der ein Song immer true, und ein Artist immer false zurückgibt (denn ein Künstler ist im Baum nie ein Blatt).
Es eird auf jeden Fall ein Knoten über insertNodeInto(...) eingefügt (Debugger)
Die Frage ist jetzt, wie bringe ich den JTree dazu, mir den Baum anzuzeigen? Ich vermute es fehlt noch irgendetwas in insertNodeInto(...) oder NodesWerrInserted(...).
Danke schonmal im Voraus, ich weiß echt nicht weiter.
-
Musst du unbedingt die Listener selbst schreiben? Überhaupt soviel selbst schreiben?
Leite doch von DefaultTreeModel ab und überschreibe nur was unbedingt sein muss?!
MfG SideWinder
-
Ich hab ja den Listener gar nicht selbst geschrieben. Nur die Nodes und das Model.
Die Nodes möchte ich schon gerne selbst schreiben, damit ich direkt auf die Struktur zugreifen kann und über das Model direkt an alle Daten komme. Das hat u.A. den Vorteil, dass ich wie gesagt aus dem Model später per DOM direkt in XML speichern kann (so ist jedenfalls meine Vorstellung, korrigiert mich sonst bitte).
Ich bin natürlich für andere Lösungen immer offen.
-
So, ich hab jetzt mal SideWinders Vorchslag aufgegriffen und benutze das DefaultTreeModel und meine Node-Klassen implementieren MutableTreeNode.
Ich habe zwar noch Probleme mit der Darstellung, aber das klappt schon wesentlich besser.
Danke für eure Mühen!