# JTree Probleme



## maxes (13. Sep 2003)

hi ich hoffe es kann mir jemand helfen....
ich habe einen SQL Baum der auch richtig ausgelesen wird und in ein arraylist gespeichert wird jetzt möchte ich diese daten in einem baum darsellen lassen nur leider verliert meine klasse in jedem schleifendurchlauf die Objekte (knoten1 - 4)
gibt es eine ander möglichkeit die daten aus der arraylist zu bekommen ohne die objekte zu verlieren??

Danke für die hilfe

LG Markus
    for ( int ast = 0; ast <  anzahl_ast ; ast++ )
    {
        objTree = (Tree) objTrees.colTrees.get(ast);



        if(objTree.get_tiefe() >= 2)
        {
            DefaultMutableTreeNode knoten1 = new DefaultMutableTreeNode( objTree.get_bezeichnung() );

            if(objTree.get_tiefe() >= 3 && objTree.get_tiefe() != 2)
            {
                DefaultMutableTreeNode knoten2 = new DefaultMutableTreeNode( objTree.get_bezeichnung() );
                //knoten1.add( knoten2 );   

                if(objTree.get_tiefe() >= 4 && objTree.get_tiefe() != 3)
                {
                    DefaultMutableTreeNode knoten3 = new DefaultMutableTreeNode( objTree.get_bezeichnung() );
                    //knoten2.add( knoten3 );   

                    if(objTree.get_tiefe() == 5 && objTree.get_tiefe() != 4)
                    {
                        DefaultMutableTreeNode knoten4 = new DefaultMutableTreeNode( objTree.get_bezeichnung() );
                        knoten3.add( knoten4 );   
                    }
                    else
                    {
                        knoten2.add( knoten3 );
                    }
                }
                else
                {
                    knoten1.add( knoten2 );
                }
            }
            else
            {
                root.add( knoten1 );
            }
        }
    }


----------



## schalentier (13. Sep 2003)

also ich find das codeschnipsel sehr verwirrend irgendwie. 
ich nehme mal an, du hast so eine sql struktur:

```
table{ string bez, int tiefe }
```
Das bedeutet du willst ein Baum in einer solchen Struktur aufbauen:


```
-+ Root
  -+ Tiefe1
    -+ Tiefe2
      -+ Tiefe3
        -+ Tiefe4
          -- obj1
          -- obj2
        -- obj3
      -- obj4
    -- obj5
  -- obj6
```

Also solltest du zuerst mal die Struktur selbst aufbauen:

```
DefaultMutableTreeNode root = createNode("Root")
DefaultMutableTreeNode ast[] = new DefaultMutableTreeNode[4];
for(int i=0;i<4;i++) ast[i] = createNode("Tiefe "+(i+1));
```

Dann läufst du durch deine Rows und fügst jedes Objekt in den Ast der entsprechenden Tiefe ein:

```
for ( int ast = 0; ast < anzahl_ast ; ast++ ) 
{ 
  objTree = (Tree) objTrees.colTrees.get(ast); 
  DefaultMutableTreeNode currNode = createNode(objTree);
  tiefe[objTree.get_tiefe()-1].add( currNode );
}
```

okay, habs nich getestet, sollte aber klappen. Dennoch ist das eine unübliche Art einen Baum in einer Tabelle abzuspeichern. Besser wäre folgende Struktur:

```
treetable{ int uid, string bez, int fk_parent }
```
Wobei uid der primarykey ist und fk_parent auf das übergeordnete Element zeigt (Foreignkey). Wie man eine solche Struktur umsetzt, sei dem Leser überlassen  :wink: 

viel spass dabei
schalentier


----------



## maxes (15. Sep 2003)

hi vielen dank für die hilfe der code bringt mich sicher weiter....
dachte mir schon, dass mein posting für verwirrung sorgen wird hier noch mal ein paar details

die datenbank:

TreeID, LinkeID, RechteID, Bezeichnung

also ein Nested Sets-Tree

die datensätze werden nun astförmig ausgelesen,

Root                       ----Knoten
--[-Transporte         ----Knoten
------[- LKW            ----Knoten
----------[- ?????     ----Ast
-------[- Zug             ----Knoten
--[-Material
-------[- Erde
----------[- normal
----------[- xxx???
-------[- Stein
----------[- marmor
----------[- ??????

jeder datensatz wird in einem objekt gespeichert und die objekte dann gesamt in einer arraylist

danach werden die objekte in einer schleife wieder ausgelesen und die werte mit der melthode an das Treeobjekt übergeben und dann sollte sich ein baum aufbauen ich weiß aber nicht wie ich das anstellen soll

LG markus


----------



## schalentier (15. Sep 2003)

hmm. also hast du ein baum, bei dem jeder knoten nur maximal 2 kinder haben kann.. bissel seltsam, aber okay.

um daraus einen baum zu bauen, würd ich das so machen:
1. Array aus DB aufbauen (so wie du beschrieben hast, aber die DB-IDs in den entsprechenden ArrayOffset umwandeln)
2. Zweites Array mit TreeNodes aufbauen (jeder TreeNode wird mit "Bezeichner" initialisiert)
3. (pseudocode)

```
foreach( treeNode in arrayList )
{
  treeNode.add( arrayList[ treeNode.LinkeID ] );
  treeNode.add( arrayList[ treeNode.RechteID] );
}
```
4. du musst noch irgendwie den Wurzelknoten finden. entweder du markierst diesen in der db als root, oder du musst den knoten finden, auf den keine Linke/RechteID zeigt. 

so irgendwie. is aber für meinen geschmack zu unflexibel. nimm besser eine 1:n beziehung zwischen papa-kind elementen (so wie in meinem anderen posting).

noch einfach gehts mit jdo. nur so als tipp.

viel spass.


----------



## maxes (16. Sep 2003)

nein ich kann so viele kinder haben wie ich will, klingt zwar komisch ist aber so *gg*
und zwag geht das so wie auf dem bild mit linker und rechter ID







was ist eigentlich jdo


----------



## schalentier (16. Sep 2003)

komischer baum, aber hier die lösung:
Die klasse Node is einfach eine zeile deiner tabelle.

ich mach mir neben der liste mit allen knoten noch 2 hashmaps, um auf knoten über RechteID und LinkeID zugreifen zu können.
dann fang ich bei der id=1 (root) an und guck, ob es einen knoten mit id+1 (=2) als LinkeID gibt. is das so, dann mach ich das solange, bis das nicht mehr stimmt. (nach unten wandern).
jetzt mach ich das gleiche nur mit dem vergleich, ob es einen knoten gibt, mit id+1 als RechteID. (nach oben wandern). 
beim runterwandern füge ich den neuen knoten dem aktuellen knoten hinzu (als kind), beim hochwandern setzte ich den aktuellen knoten auf den papa-knoten.

trotzdem sehe ich den sinn nich wirklich. gut, das aufbauen läuft inner schleife ab (nicht rekursiv), aber hinzufügen eines knotens is sehr umständlich. macht nur bei richtig großen bäumen sinn, die ich anfangs aus der db lade und am ende wieder komplett neu (neue ids) in die db schreibe, oder?

jdo = JavaDataObjects, eine spezifikation von sun, um mit persistenten objekten zu arbeiten, ohne sich gedanken über db zu machen...
musst ma googlen.


```
package de.tests.strangeTree;

import javax.swing.*;
import javax.swing.tree.*;
import java.util.*;
import java.awt.*;

public class Builder {
    ArrayList nodes;
    HashMap upMap, downMap;

    public Builder() {
        nodes = new ArrayList();
    }

    public static void main(String[] args) {
        Builder b = new Builder();
        b.addNode(new Node(1,22,"Root"));
        b.addNode(new Node(2,7,"A"));
        b.addNode(new Node(3,6,"A1"));
        b.addNode(new Node(4,5,"A1I"));
        b.addNode(new Node(8,13,"B"));
        b.addNode(new Node(9,10,"B1"));
        b.addNode(new Node(11,12,"B2"));
        b.addNode(new Node(14,21,"C"));
        b.addNode(new Node(15,20,"C1"));
        b.addNode(new Node(16,17,"C1I"));
        b.addNode(new Node(18,19,"C1II"));

        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        Container pane = frame.getContentPane();
        pane.add( b.build(), "Center");
        frame.pack();
        frame.setVisible( true );
    }

    public JTree build()
    {
        upMap = new HashMap();
        downMap = new HashMap();

        for( Iterator iterator = nodes.iterator(); iterator.hasNext(); )
        {
            Node node = ( Node )iterator.next();
            downMap.put(new Integer(node.getLeftID()),node);
            upMap.put(new Integer(node.getRightID()),node);
        }

        int currID = 1;
        boolean down=true;
        DefaultMutableTreeNode currNode = createNode(getNode(currID));
        DefaultMutableTreeNode root = currNode;
```
Jetzt wird interessant:

```
while( currNode!=null )
        {
            int nextID = currID + 1;
            if( down )
            {
                if( isDownID(nextID) )
                {
                    DefaultMutableTreeNode nextNode = createNode(getNode(nextID));
                    currNode.add(nextNode);
                    currNode = nextNode;
                    currID = nextID;
                } else
                {
                    down = false;
                    currID = nextID;
                }
            } else
            {
                currNode = (DefaultMutableTreeNode )currNode.getParent();
                if( !isDownID(nextID) )
                {
                    currID = nextID;
                } else
                {
                    down = true;
                }
            }
        }
        return new JTree(root);
    }
```
Und noch ein paar hilfsmethoden:

```
protected boolean isDownID( int id )
    {
        return downMap.containsKey(new Integer(id));
    }
    protected Node getNode(int id)
    {
        if( isDownID(id) ) return (Node )downMap.get(new Integer(id));
        return (Node )upMap.get(new Integer(id));
    }

    public DefaultMutableTreeNode createNode(Node n )
    {
        return new DefaultMutableTreeNode(n.getDesc());
    }
    public void addNode( Node n )
    {
        nodes.add(n);
    }
}
```


```
package de.tests.strangeTree;

public class Node {
    int leftID;
    int rightID;
    String desc;

    public Node(int leftID, int rightID, String desc) {
        this.leftID = leftID;
        this.rightID = rightID;
        this.desc = desc;
    }

    public String getDesc()
    {
        return desc;
    }

    public int getLeftID()
    {
        return leftID;
    }

    public int getRightID()
    {
        return rightID;
    }
}
```

viel spass


----------



## maxes (18. Sep 2003)

vielen dank erst mal, das war echt toll was du da in der kurzen zeit geleistet hast   :wink: 
und es funktioniert einwandfrei

jetzt hab ich natürlich noch ne frage

kann man an jedes element, also jede node einen tooltip anhängen bzw die id mitübergeben nicht nur den beschreibenden text?

und wie kann ich mir dann die id bzw wenn das nicht geht den text durch zb doppelcklick mit der maus wieder laden?

Lg markus


----------

