# JTree nach Node durchsuchen und expanden



## atarifreak (15. Okt 2004)

Hallo!

Ich bin seit einigen Tagen schon am Grübeln, und irgendwie komme ich nicht mehr weiter. Ich habe auch die Suchfunktion bemüht, aber irgendwie bringt die nicht die Lösung meines Problems.

Also:
Ich befülle mein JTree mit einer eigenen Klasse, welche ich von DefaultMutableTreeNode abgeleitet habe, mit dem Unterschied, dass diese eigene Node noch so einige zusätzliche Infos, u.a. z.B. eine bestimmte ID, speichert. Nun möchte ich, dass das JTree nachträglich nach dieser Node durchsucht wird, diese dann komplett bis zur Rootnode aufgeklappt wird.

Doch ich scheitere schon am Anfang, dem Auffinden der Rootnode. Wie komme ich über das JTree an das Teil? Mir schwebte dann vor, diese dann rekursiv zu durchsuchen, um auf diesem Weg die gesuchte Node zu finden. Wie bringe ich dann das JTree dazu, diesen Pfad zu expandieren? Kann mir da jemand helfen, bin völlig ratlos?   

Vielen Dank!

AF


----------



## Beni (15. Okt 2004)

Du benötigst das TreeModel, um an die einzelnen Nodes zu kommen. An das Model kommst du übe die Methode JTree#getModel().

Und Nodes aufklappen kannst du mit expandPath (selektieren mit _setSelectionPath_).


----------



## atarifreak (15. Okt 2004)

Vielen Dank für die schnelle Hilfe.   

Aber wie bekomme ich den TreePath, damit ich ihn expandieren kann? Die Methode getPath() gibt mir nur eine TreeNode zurück, und casten kann man den Kram nicht in einen TreePath. Außerdem bietet DefaultMutableTreeNode keine Methode, die einen TreePath liefert.  ???:L 

Kannst Du mir da noch einen Tip geben?


----------



## atarifreak (15. Okt 2004)

Also mal etwas genauer. Ich habe zwei Lösungsansätze, ich weiß nur nicht, ob die richtig sind. Mir geht es erstmal um das Aufsuchen der richtigen Node.

Variante 1: Es wird das komplette TreeModel an die rekursive Funktion übergeben. Haken: Das Casten klappt nicht bei der rekursiven Übergabe. Man kann leider nicht, wie z.B. bei XML, eine Node als Model übergeben.

Aufruf:

```
searchTree(strErgId, (DefaultTreeModel)tr.getModel());
```

Methode:

```
private boolean searchTree(String strKey, DefaultTreeModel tmParent)
	{
		boolean found = false;
		
		if (tmParent.getChildCount(tmParent) > 0)
		{
			for (int i=0; i<tmParent.getChildCount(tmParent); i++)
			{
				System.out.println(tmParent.getChild(tmParent, i));
				searchTree(strKey, (DefaultTreeModel)tmParent.getChild(tmParent, i));
			}
		}
	}
```

Variante 2: Es wird vor Einsprung in die Rekursion die Rootnode des JTrees ermittelt und diese in einen TreePath gecastet. Dieser wird dann in die abgeleitete Nodeklasse gecastet, um an die Informationen heranzukommen.

Aufruf:

```
searchTree(strErgId, (TreePath)tr.getModel().getRoot());
```

Methode:

```
private boolean searchTree(String strKey, TreePath tpParent)
	{
		CmNode cn = (CmNode)tpParent.getLastPathComponent();
		if (cnParent.getChildCount()>0)
		{
			for (int i=0; i<cnParent.getChildCount(); i++)
			{
				CmNode cnChild = (CmNode)cnParent.getChildAt(i);
				if (cnChild.getId().equals(strKey))
				{
					found = true;
					TreePath tp = (TreePath)cnChild.getPath();
					tr.expandPath(tp);
				}
				else
					found = searchTree(strKey, cmChild);
			}
		}
		return found;
	}
```

Habe ich da vielleicht einen generellen Denkfehler?


----------



## Beni (15. Okt 2004)

Also zum suchen: übergib der rekursiven Methode ein Parent-Node, und das TreeModel:


```
search( Object node, TreeModel model ){
  // irgendwie überprüfen, ob "node" der gesucht node ist, und falls
  // ja, abbrechen. (ein boolean zurückgeben oder sowas, wie du das
  // bei deinem "searchTree" schon gemacht hast

  for( int i = 0, n = model.getChildCount( node ); i<n; i++ ){
    search( model.getChild( node, i ), model );
  }
}
```

Und ein TreePath musst du dir selbst zusammenbauen. Wenn du das DefaultTreeModel verwendest, kannst du mal versuchen mit der Methode "getPathToRoot(TreeNode aNode)" ein Array von Nodes zu erhalten. Diesen Arrays übergibst du dem Konstruktor von TreePath.


----------



## atarifreak (15. Okt 2004)

Yes! Das wars!    Vielen Dank für Deine Hilfe!

Falls es interessiert, der komplette Quelltext, wobei überall, wo CmNode steht, DefaultMutableTreeNode zu sehen ist:


```
private boolean searchTree(String strKey, TreeModel tmParent, int intParentIndex, int intChildCount, TreeNode tnParent)
	{
		boolean found = false;
		if (intChildCount > 0)
		{
			for (int i=0; i<intChildCount; i++)
			{
				CmNode cn = (CmNode)tnParent.getChildAt(i);
				TreeNode tnNewParent = tnParent.getChildAt(i);
				int intNewParentIndex = tnParent.getIndex(tnNewParent);
				System.out.println(cn);
				if (cn.getId().equals(strKey))
				{
					System.out.println("hier:" + cn);
					TreePath tp = new TreePath(cn.getPath());
					tr.expandPath(tp);
					tr.setSelectionPath(tp);
				}
				searchTree(strKey, tmParent, intNewParentIndex, tnNewParent.getChildCount(), tnNewParent);
			}
		}
		return found;		
	}
```

Aufruf mit:

```
TreeNode tn = (TreeNode)tr.getModel().getRoot();
searchTree(strErgId, tr.getModel(), tn.getIndex(tn), tr.getModel().getChildCount(tn), tn);
```

AF


----------

