# Tree - ArrayList Zuordnung!



## sunnyfriday (24. Sep 2008)

Hallo Leute,


Habe ein kleines Problem. Und zwar habe ich eine ArrayList von Objekten.
Ich möchte diese ArrayList in einem Tree darstellen.


Jedoch möchte ich eine Zuordnung der Tree-Nodes zu den Arraylist-Objekte haben.
Zb. Wenn ich im Tree den Node x lösche, dann sollte das entsprechende Objekt im arrayList auch gelöscht werden.
    oder wenn ich im tree einen neu neues Node hinzufüge, dann soll auch ein Objekt im entsprechenden Arraylist angelegt werden.

Wie bekomme ich diese Zuordnung Tree - ArrayList hin??

Beispiel:


```
class Kunde {

 private String name;
 private String vorname;

}
```


```
.
.
ArrayList<Kunde> kundenList = new ArrayList<Kunde>();
.
.
```


Kunden
|
 - kunde1
 - kunde2
 - kunde3
 - kunde4

hoffe jemand kann helfen...

Danke


----------



## Marco13 (24. Sep 2008)

Man kann ein TreeModel erstellen, das intern diese ArrayList kennt (oder verwendet). Allerdings wird dieses automatische Aktualisieren dann erstmal nur in der Richtung TreeModel->ArrayList funktionieren, und nicht umgekehrt.


----------



## sunnyfriday (24. Sep 2008)

Hallo Marco,

Danke für den Tipp mit dem TreeModel.



Würde es funktionieren, wenn ich eine Klasse habe, die TreeModel implementiert und eine Arraylist verwaltet.

So das ich in der ArrayList von außen elemente hinzufügen,entfernen,verschieben kann und automatisch der Baum aktualisert wird.??

Oder wenn ich im tree einen Node entferne, daß ich in der Arraylist das entsprechende Element entferne?? 

Würde das mit einem TreeModel funktionieren???

gruß


----------



## Marco13 (24. Sep 2008)

_Würde es funktionieren, wenn ich eine Klasse habe, die TreeModel implementiert und eine Arraylist verwaltet._

Wie gesagt: ""Ja""

_So das ich in der ArrayList von außen elemente hinzufügen,entfernen,verschieben kann und automatisch der Baum aktualisert wird.??_

Wie gesagt: Nein

_Oder wenn ich im tree einen Node entferne, daß ich in der Arraylist das entsprechende Element entferne?? _

Wie gesagt: Ja

_Würde das mit einem TreeModel funktionieren???_

Wie gesagt: Jein.


Wenn sich in dem TreeModel irgendwas ändert, dann kann man (weil man das TreeModel ja SELBST geschrieben hat) dafür sorgen, dass alle änderungen auch in die ArrayList übertragen werden.

Umgekehrt geht das (erstmal) NICHT: Wenn man an der ArrayList irgendwas ändert, dann kriegt davon niemand etwas mit.

Ich weiß nicht, in welchen Zusammenhang du das brauchst, was du genau erreichen willst, usw. aber evtl. wäre es sinnvoll, dir eine eigene Klasse "KundenDaten" zu schreiben, die deine Kunden speichert, und alle gewünschten Operationen anbietet. Alle diese Operationen könnten "KundenEvents" an "KundenListener" senden, und es könnte Implementierungen für "KundenListener" geben, die die ArrayList und ein TreeModel aktualisieren. Aber das sind Designentscheidungen, die DU treffen musst.


----------



## Michael... (24. Sep 2008)

Anstatt TreeModel zu implementieren, würde ich von DefaultTreeModel (welches TreeModel implementiert) erben und darin die ArrayList verwalten.


----------



## sunnyfriday (24. Sep 2008)

Hallo,

es scheint echt kompliziert zu sein.

Was ich konkret brauche ist:

ich habe eine ArrayList<Kunde> kundenlist.

1. die kundenliste als tree ausgeben.
2. aus dem tree heraus. kunden löschen, einfügen, reihenfolge ändern. => das ganze dann auch auf die kundenlist übertragen.

3. die modifizierte KundenList dann weitergeben an andere Funktion.


Ich werde mich mal damit auseinandersetzen... danke nochmals


----------



## sunnyfriday (25. Sep 2008)

Hallo,

Soll ich jetzt die Schnittstelle TreeModel implementieren oder von der Klasse DefaultTreeModel erben??

Bei DefaultTreeModel gibt es Funktionen die in meinem Fall zu gebrauchen sind.

wie z.b. insertNodeInto()...

Wenn ich mich für die DefaultTreeModel klasse entscheide, muss ich dann die ganzen Methoden überschreiben???

Ich weis jetzt nicht welche Variante ich nehmen soll.  Weis jemand Rat??

Gruss


----------



## Michael... (25. Sep 2008)

Der Vorteil wenn man DefaultTreeModel verwendet ist, dass man nur die Methoden überschreiben muss, die man will. D.h. die Methoden, welche mittels TreeModel implementiert wurden, sind schon definiert. In Deinem Fall würde das wahrscheinlich bedeuten Du überschreibst nur insertNodeInto und kannst dann z.B. prüfen ob der eingefügte Knoten für Deine Liste relevant ist.


----------



## Marco13 (25. Sep 2008)

Es gibt verschiedene Möglichkeiten. Du kannst auch ein DefaultTreeModel verwenden, und dort einen Listener dranhängen, der dann deine Liste aktualisiert.


----------



## sunnyfriday (25. Sep 2008)

Hallo Michael,

Danke für deine Antwort...

Ich muss aber auch alle Funktionen der TreeModel überschreiben. getChild(), getChildCount(), etc..
die muss ich ja auch anpassen.  

Wie sind diese Funktionen in der DefaultTreeModel Klasse implenetiert??? auf welche Datenstruktur werden sie angewendet?? 

wo kann ich die Implementierungen der Funktionen von DefaultTreeModel anschauen??

Boaaa ... ich finde es echt kompliziert...

Wie gesagt:

Ich habe einfach eine ArrayList<Kunde>

Da möchte ich einfach Kunden über den Tree einfügen, löschen, Reihenfolge ändern. ;-(

Gruss sunny


----------



## Marco13 (25. Sep 2008)

*seufz*

```
// Based on [url]http://java.sun.com/docs/books/tutorial/uiswing/examples/components/DynamicTreeDemoProject/src/components/DynamicTreeDemo.java[/url]
// For [url]http://www.java-forum.org/de/viewtopic.php?t=75372&highlight=[/url]


import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.UIManager;

import javax.swing.JTree;
import java.util.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeSelectionModel;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;

import java.net.URL;
import java.io.IOException;
import java.awt.Dimension;
import java.awt.GridLayout;

import java.awt.GridLayout;
import java.awt.Toolkit;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.MutableTreeNode;
import javax.swing.tree.*;
import javax.swing.tree.TreeSelectionModel;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.tree.DefaultMutableTreeNode;

class Customer
{
    private String name;

    public Customer(String name)
    {
        this.name = name;
    }

    public String toString()
    {
        return name;
    }


}


class ListTreeModelListener implements TreeModelListener
{

    private List<Customer> list;

    public ListTreeModelListener(List<Customer> list)
    {
        this.list = list;
    }

    public void treeNodesChanged(TreeModelEvent e)
    {
    }
    public void treeNodesInserted(TreeModelEvent e)
    {
        updateList((TreeModel)e.getSource());
    }
    public void treeNodesRemoved(TreeModelEvent e)
    {
        updateList((TreeModel)e.getSource());
    }
    public void treeStructureChanged(TreeModelEvent e)
    {
    }


    private void updateList(TreeModel treeModel)
    {
        Object root = treeModel.getRoot();
        list.clear();
        int n = treeModel.getChildCount(root);
        for (int i=0; i<n; i++)
        {
            DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode)treeModel.getChild(root, i);
            Object object = treeNode.getUserObject();
            Customer customer = (Customer)object;
            list.add(customer);
        }
        System.out.println("List now: "+list);
    }
}






public class TreeTest3 extends JPanel implements ActionListener {

    private int newNodeSuffix = 1;
    private static String ADD_COMMAND = "add";
    private static String REMOVE_COMMAND = "remove";
    private static String CLEAR_COMMAND = "clear";

    private DynamicTree treePanel;

    public TreeTest3()
    {
        super(new BorderLayout());

        //Create the components.
        treePanel = new DynamicTree();


        //=========================================================

        List<Customer> customers = new ArrayList<Customer>();
        customers.add(new Customer("First"));
        customers.add(new Customer("Second"));
        customers.add(new Customer("Third"));
        customers.add(new Customer("Fourth"));

        for (Customer customer: customers)
        {
            treePanel.addObject(null, customer);
        }

        treePanel.treeModel.addTreeModelListener(new ListTreeModelListener(customers));



        //=========================================================



        JButton addButton = new JButton("Add");
        addButton.setActionCommand(ADD_COMMAND);
        addButton.addActionListener(this);

        JButton removeButton = new JButton("Remove");
        removeButton.setActionCommand(REMOVE_COMMAND);
        removeButton.addActionListener(this);

        JButton clearButton = new JButton("Clear");
        clearButton.setActionCommand(CLEAR_COMMAND);
        clearButton.addActionListener(this);

        //Lay everything out.
        treePanel.setPreferredSize(new Dimension(300, 150));
        add(treePanel, BorderLayout.CENTER);

        JPanel panel = new JPanel(new GridLayout(0,3));
        panel.add(addButton);
        panel.add(removeButton);
        panel.add(clearButton);
        add(panel, BorderLayout.SOUTH);
    }


    public void actionPerformed(ActionEvent e) {
        String command = e.getActionCommand();

        if (ADD_COMMAND.equals(command)) {
            //Add button clicked
            treePanel.addObject(new Customer("New Node " + newNodeSuffix++));
        } else if (REMOVE_COMMAND.equals(command)) {
            //Remove button clicked
            treePanel.removeCurrentNode();
        } else if (CLEAR_COMMAND.equals(command)) {
            //Clear button clicked.
            treePanel.clear();
        }
    }

    /**
     * Create the GUI and show it.  For thread safety,
     * this method should be invoked from the
     * event-dispatching thread.
     */
    private static void createAndShowGUI() {
        //Create and set up the window.
        JFrame frame = new JFrame("TreeTest3");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //Create and set up the content pane.
        TreeTest3 newContentPane = new TreeTest3();
        newContentPane.setOpaque(true); //content panes must be opaque
        frame.setContentPane(newContentPane);

        //Display the window.
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        //Schedule a job for the event-dispatching thread:
        //creating and showing this application's GUI.
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}




class DynamicTree extends JPanel {
    protected DefaultMutableTreeNode rootNode;
    public DefaultTreeModel treeModel;
    protected JTree tree;
    private Toolkit toolkit = Toolkit.getDefaultToolkit();




    public DynamicTree() {
        super(new GridLayout(1,0));

        rootNode = new DefaultMutableTreeNode("Root Node");
        treeModel = new DefaultTreeModel(rootNode);

        tree = new JTree(treeModel);
        tree.setEditable(true);
        tree.getSelectionModel().setSelectionMode
                (TreeSelectionModel.SINGLE_TREE_SELECTION);
        tree.setShowsRootHandles(true);

        JScrollPane scrollPane = new JScrollPane(tree);
        add(scrollPane);
    }

    /** Remove all nodes except the root node. */
    public void clear() {
        rootNode.removeAllChildren();
        treeModel.reload();
    }

    /** Remove the currently selected node. */
    public void removeCurrentNode() {
        TreePath currentSelection = tree.getSelectionPath();
        if (currentSelection != null) {
            DefaultMutableTreeNode currentNode = (DefaultMutableTreeNode)
                         (currentSelection.getLastPathComponent());
            MutableTreeNode parent = (MutableTreeNode)(currentNode.getParent());
            if (parent != null) {
                treeModel.removeNodeFromParent(currentNode);
                return;
            }
        }

        // Either there was no selection, or the root was selected.
        toolkit.beep();
    }

    /** Add child to the currently selected node. */
    public DefaultMutableTreeNode addObject(Object child) {
        DefaultMutableTreeNode parentNode = null;
        TreePath parentPath = tree.getSelectionPath();

        if (parentPath == null) {
            parentNode = rootNode;
        } else {
            parentNode = (DefaultMutableTreeNode)
                         (parentPath.getLastPathComponent());
        }

        return addObject(parentNode, child, true);
    }

    public DefaultMutableTreeNode addObject(DefaultMutableTreeNode parent,
                                            Object child) {
        return addObject(parent, child, false);
    }

    public DefaultMutableTreeNode addObject(DefaultMutableTreeNode parent,
                                            Object child,
                                            boolean shouldBeVisible) {
        DefaultMutableTreeNode childNode =
                new DefaultMutableTreeNode(child);

        if (parent == null) {
            parent = rootNode;
        }

    //It is key to invoke this on the TreeModel, and NOT DefaultMutableTreeNode
        treeModel.insertNodeInto(childNode, parent,
                                 parent.getChildCount());

        //Make sure the user can see the lovely new node.
        if (shouldBeVisible) {
            tree.scrollPathToVisible(new TreePath(childNode.getPath()));
        }
        return childNode;
    }

}
```


----------



## sunnyfriday (26. Sep 2008)

guten Morgen,

Wow ...danke marco... Das wird mir sicherlich helfen.
Danke vielmals... werde es mir jetzt genauer anschauen.
Danke


----------



## Marco13 (26. Sep 2008)

Relevant sind nur die ersten Beiden Klassen, und der Teil zwischen den "==========". Der Rest ist "Standard" aus dem Swing-Beispiel. (Wäre für dich sicher leichter Nachzuvollziehen, wenn DU einfach DEIN Programm in compilierbarer Form gepostet hättest.... *wink* )


----------



## sunnyfriday (26. Sep 2008)

hi marco,

super ... geht klar. Ich werde später dann meinen Code reinposten.


----------

