PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Dynamischen JTree verändern


ethrandil
2003-05-14, 22:05:24
Hiho, Java mal wieder =D

ein recht spiezielles Problem, das auhc in den Java Foren nie wirklich gelöst wurde (bzw. niemand hat seine Lösung preisgegeben ...):
Ich habe eine von JTree abgeleitete Klasse, die Dynamisch ihre Nodes generiert (basiert auf SQL).
Wenn nun ein Node geändert wird und ich 'nodeStructureChanged' aufrufe ist der Tree ganz eingeklappt. Nun möchte ich ihn aber wieder ausklappen. Dazuhabe ich mir vorher alle ausgeklappten Nodes gemerkt ( getExpandedDescendants(this.getPathForRow(0)) ) Um sie danach der Reihe nach wieder aufzuklappen ( this.expandPath(TreePath) ).

Leider funktioniert das ganze nicht! Wenn ich nur eine Ebene underm Root aufgeklappt habe gehts noch, aber wenn ich mehr habe nicht!
Ich habe auch mal versucht das Ausklappen von 'oben nach unten' zu machen, indem ich die Reihenfolge des Ausklappens sortiere: Nix!

Wie kann ich das machen?? Hat jemand eine Ahnung?

Eth.

Hier der Code für die updadtefunktion:

public void update(){
DefaultTreeModel dtm = (DefaultTreeModel) this.getModel();

Enumeration expanded = this.getExpandedDescendants(this.getPathForRow(0));

dtm.nodeStructureChanged((DefaultMutableTreeNode)this.getPathForRow(0).getLastPa thComponent());

Vector paths = new Vector();
Vector levels = new Vector();

int maxLevel = -1;
int actualLevel = 0;

while(expanded.hasMoreElements()){
TreePath tp = (TreePath)expanded.nextElement();
paths.add(tp);
StringTokenizer st = new StringTokenizer(tp.toString(), ",");
levels.add(paths.indexOf(tp),new Integer(st.countTokens()));
if(st.countTokens() > maxLevel)
maxLevel = st.countTokens();
}
Object[] pathsV = paths.toArray();
Object[] levelsV = levels.toArray();

while(actualLevel <= maxLevel){
for(int i = 0; i< levelsV.length; ++i){
if(((Integer)levelsV[i]).intValue() == ActualLevel &&
!this.isExpanded(new TreePath((TreePath)pathsV[i]))){

System.out.print(pathsV[i]);
this.expandPath((TreePath)pathsV[i]);
this.setExpandedState((TreePath)pathsV[i], true);
if(this.isExpanded((TreePath)pathsV[i]))
System.out.println("done");
else
System.out.println("failed");
}
}
actualLevel++;
}
}

EDIT: Ich weiß auch das der Code zum sortieren nicht schön ist, den hab ich halt nur mal zum probieren reingebastelt, ums zu testen: negativ.

Captain America
2003-05-19, 00:54:33
Schon was rausgefunden? :D Wenn du mir den ganzen Code schickst guck ich selbst mal. Sonst zu faul ein Testgerüst dafür zu basteln.

ethrandil
2003-05-19, 14:31:13
Ich kann dir natürlich meine Tree-kKomponente schicken, aber dann bräuchtest du auch meine Datenbankanbindung samt datenbank ;)

Ne lösung habe ich leider nicht, ich hab das mal nach hinten in den TODOs verbannt...

ethrandil
2003-05-19, 17:03:34
Lösung da =)


DefaultTreeModel dtm = (DefaultTreeModel) this.getModel();
Enumeration expanded = this.getExpandedDescendants(this.getPathForRow(0));
Vector expandedRows = new Vector(50);

while(expanded.hasMoreElements()){
expandedRows.add(new Integer(this.getRowForPath((TreePath)expanded.nextElement())));
}

dtm.nodeStructureChanged((DefaultMutableTreeNode)this.getPathForRow(0).getLastPa thComponent());

Collections.sort(expandedRows);

for(int i= 0; i<expandedRows.size(); ++i)
this.expandRow(((Integer)expandedRows.get(i)).intValue());

EDIT: nee wird nicht gehen fällt mir grade ein, shice

ethrandil
2003-05-19, 19:14:12
Okay, ich habe ne lösung.

Das problem war: Wenn ich mir die tree-pfade speicher, um sie nachher auszuklappen funktioniert das nicht, da die pfade ja andere objekte sind, weil ich sie bei jedem ausklappen neu generiere.

Die Lösung: Ich habe eine methode für TreePath s geschrieben, die aus dem Tree den pfad sucht, der den selben String (Eigenschaften) hat.

Pooh, wie kann man nur einen Tag mit so kleinigkeiten verdaddeln :nenene:

am anfang des aktualisierungsprozesses werden dann mit
Enumeration expanded = this.getExpandedDescendants(this.getPathForRow(0));
Im tree die aktuell ausgeklappten nodes gespeichert.
Dann wird er geupdated, ud erwartungsgemäß ist er eingeklappt.
dann macht eine Methode
expand(expanded);
den Rest:
Sie besorgt sich ertmal mit
sort(expanded);
einen Vector, der nach tiefe des Nodes sortiert ist.
Dann wird für jeden node der reihe nach das äquivalent im 'aktuell vorhandenen' tree gesucht, da beim updaten quasi alle nodes verloren gingen.
Dieser wird dann ausgeklappt.

Son shice abba auch. ich glaub ich schreib mein erstes Tutorial ;)
Thema: SQLBasierter JTree
Eine klasse SQLJTree kommt noch dazu, mit einem "SQLExpansionListener"...
Code:

JTree:

public void expand(Enumeration toExpand){
Vector oldPaths = sort(toExpand);
for(int i=0; i< oldPaths.size(); ++i){
TreePath element = (TreePath) oldPaths.get(i);
System.out.println("trying to add "+element);
this.expandPath(this.getPathByName(element.toString()));
}
}

public TreePath getPathByName(String name){
TreePath[] tp = this.getPathBetweenRows(0, this.getRowCount());

for(int i=0; i< tp.length; ++i){
if(tp[i].toString().equals(name)){
System.out.println("for name "+name+" I found "+tp[i]);
return tp[i];
}
}
return null;
}

public Vector sort(Enumeration expanded){
Vector paths = new Vector();
Vector levels = new Vector();

int maxLevel = -1;
int actualLevel = 0;

while(expanded.hasMoreElements()){
TreePath tp = (TreePath)expanded.nextElement();
paths.add(tp);
StringTokenizer st = new StringTokenizer(tp.toString(), ",");
levels.add(paths.indexOf(tp),new Integer(st.countTokens()));
if(st.countTokens() > maxLevel)
maxLevel = st.countTokens();
}
Object[] pathsV = paths.toArray();
Object[] levelsV = levels.toArray();
Vector sorted = new Vector();

while(actualLevel <= maxLevel){
for(int i = 0; i< levelsV.length; ++i){
if(((Integer)levelsV[i]).intValue() == actualLevel){
sorted.add(pathsV[i]);
}
}
actualLevel++;
}
return sorted;
}

public void update(){
DefaultTreeModel dtm = (DefaultTreeModel) this.getModel();
Enumeration expanded = this.getExpandedDescendants(this.getPathForRow(0));
dtm.nodeStructureChanged((DefaultMutableTreeNode)this.getPathForRow(0).getLastPa thComponent());

this.expand(expanded);
}

:kotz: (jaja, das sortieren sieht verdächtig nach optimierbar aus ...