# JTree - Explorer mit nur eingeschränkter Anzeige



## pabu1983 (4. Jan 2010)

Hallo Zusammen,

ich bin jetzt schon seit Wochen dran mein eigenen Explorer für ein Progrämmchen zusammen zu klicken.
Ich habe auch eine Lösung die schon ganz gut passt. Nur fehlt eine wichtige Eigenschaft und ich hoffe das die Pro's hier im Forum mir helfen können um den nötigen Code hierfür zu ergänzen.

Also ich habe einen JTree der mir die Laufwerke und deren Ordner anzeigt. Nun will ich das auch die Dateien angezeigt werden. ABER - WICHTIG - nicht alle Dateien. Nur die, die mit den Endungen txt, jpg und png enden. Im Prinzip hätte ich gern den Windows-Explorer mit Dateiendungsfilter 

Hier den JTree an dem ich schon seit Wochen das Problem versuche zu lösen...

```
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author pabu
 */

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

public class DirTree extends JScrollPane {
    public static final ImageIcon ICON_COMPUTER = new ImageIcon("D:/Projekte/2009-11/Java_GUI/Conti_Tree/Icons/monitor.png");
    public static final ImageIcon ICON_DISK = new ImageIcon("D:/Projekte/2009-11/Java_GUI/Conti_Tree/Icons/festplatte.png");
    public static final ImageIcon ICON_FOLDER = new ImageIcon("D:/Projekte/2009-11/Java_GUI/Conti_Tree/Icons/ordner_zu.png");
    public static final ImageIcon ICON_EXPANDEDFOLDER = new ImageIcon("D:/Projekte/2009-11/Java_GUI/Conti_Tree/Icons/ordner_auf.png");
    protected JTree m_tree;
    protected DefaultTreeModel m_model;

    public DirTree() {
        super();
        DefaultMutableTreeNode top = new DefaultMutableTreeNode(new IconData(ICON_COMPUTER, null, "Computer"));
        DefaultMutableTreeNode node;
        
        File[] roots = File.listRoots();                                        // START - Befüllung des Baumes
        for (int k=0; k<roots.length; k++) {                                    // Es werden alle Laufwerke
            node = new DefaultMutableTreeNode(new IconData(ICON_DISK,           // eingelesen die generell
                null, new FileNode(roots[k])));                                 // an diesem Rechner verfügbar
            top.add(node);                                                      // sind und in den Baum
            node.add(new DefaultMutableTreeNode(new Boolean(true)));            // eingefügt
        }                                                                       // ENDE - Befüllung des Baumes

        m_model = new DefaultTreeModel(top);
        m_tree = new JTree(m_model);
        m_tree.putClientProperty("JTree.lineStyle", "Angled");
        IconCellRenderer renderer = new IconCellRenderer();
        m_tree.setCellRenderer(renderer);
        m_tree.addTreeExpansionListener(new DirExpansionListener());
        m_tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
        m_tree.setShowsRootHandles(true);
        m_tree.setEditable(false);

        this.getViewport().add(m_tree);
    }
    DefaultMutableTreeNode getTreeNode(TreePath path) {
        return (DefaultMutableTreeNode)(path.getLastPathComponent());
    }
    FileNode getFileNode(DefaultMutableTreeNode node) {
        if (node == null)
            return null;
        Object obj = node.getUserObject();
        if (obj instanceof IconData)
            obj = ((IconData)obj).getObject();
        if (obj instanceof FileNode)
            return (FileNode)obj;
        else
            return null;
    }
    // Make sure expansion is threaded and updating the tree model
    // only occurs within the event dispatching thread.
    class DirExpansionListener implements TreeExpansionListener {
        public void treeExpanded(TreeExpansionEvent event) {
            final DefaultMutableTreeNode node = getTreeNode(
                event.getPath());
            final FileNode fnode = getFileNode(node);
            Thread runner = new Thread() {
                public void run() {
                    if (fnode != null && fnode.expand(node)) {
                        Runnable runnable = new Runnable() {
                            public void run() {
                                m_model.reload(node);
                            }
                        };
                        SwingUtilities.invokeLater(runnable);
                    }
                }
            };
            runner.start();
        }
        public void treeCollapsed(TreeExpansionEvent event) {}
    }

    public static void main(String argv[]) {
        JFrame frame = new JFrame();
        DirTree scrollTree = new DirTree();
        frame.setSize(200,300);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(scrollTree);
        frame.setVisible(true);
    }
}

class IconCellRenderer extends DefaultTreeCellRenderer {
    public IconCellRenderer() {
        setLeafIcon(null);
        setOpenIcon(null);
    }
    public Component getTreeCellRendererComponent(JTree tree,
        Object value, boolean sel, boolean expanded, boolean leaf,
        int row, boolean hasFocus) {
        // Invoke default implementation
        Component result = super.getTreeCellRendererComponent(tree,
            value, sel, expanded, leaf, row, hasFocus);
        DefaultMutableTreeNode node = (DefaultMutableTreeNode)value;
        Object obj = node.getUserObject();
        setText(obj.toString());
        if (obj instanceof Boolean)
            setText("Retrieving data...");
        if (obj instanceof IconData) {
            IconData idata = (IconData)obj;
            if (expanded)
                setIcon(idata.getExpandedIcon());
            else
                setIcon(idata.getIcon());
        }
        else
            setIcon(null);
        return result;
    }
}

class IconData {
    protected Icon   m_icon;
    protected Icon   m_expandedIcon;
    protected Object m_data;
    public IconData(Icon icon, Object data) {
        m_icon = icon;
        m_expandedIcon = null;
        m_data = data;
    }
    public IconData(Icon icon, Icon expandedIcon, Object data) {
        m_icon = icon;
        m_expandedIcon = expandedIcon;
        m_data = data;
    }
    public Icon getIcon() {
        return m_icon;
    }
    public Icon getExpandedIcon() {
        return m_expandedIcon!=null ? m_expandedIcon : m_icon;
    }
    public Object getObject() {
        return m_data;
    }
    public String toString() {
        return m_data.toString();
    }
}
class FileNode {
    protected File m_file;
    public FileNode(File file) {
        m_file = file;
    }
    public File getFile() {
        return m_file;
    }
    public String toString() {
        return m_file.getName().length() > 0 ? m_file.getName() :
            m_file.getPath();
    }
    // Alternatively we copud sub-class TreeNode
    public boolean expand(DefaultMutableTreeNode parent) {
        DefaultMutableTreeNode flag = (DefaultMutableTreeNode)parent.getFirstChild();
        if (flag==null)   // No flag
            return false;
        Object obj = flag.getUserObject();
        if (!(obj instanceof Boolean))
            return false;      // Already expanded
        parent.removeAllChildren();  // Remove Flag
        File[] files = listFiles();
        if (files == null)
            return true;
        Vector v = new Vector();
        for (int k=0; k<files.length; k++) {
            File f = files[k];
            if (!(f.isDirectory()))
                continue;
            FileNode newNode = new FileNode(f);
            boolean isAdded = false;
            for (int i=0; i<v.size(); i++) {
                FileNode nd = (FileNode)v.elementAt(i);
                if (newNode.compareTo(nd) < 0) {
                    v.insertElementAt(newNode, i);
                    isAdded = true;
                    break;
                }
            }
            if (!isAdded)
                v.addElement(newNode);
        }
        for (int i=0; i<v.size(); i++) {
            FileNode nd = (FileNode)v.elementAt(i);
            IconData idata = new IconData(DirTree.ICON_FOLDER,
                DirTree.ICON_EXPANDEDFOLDER, nd);
            DefaultMutableTreeNode node = new
                DefaultMutableTreeNode(idata);
            parent.add(node);
            if (nd.hasSubDirs())
                node.add(new DefaultMutableTreeNode(
                    new Boolean(true) ));
        }
        return true;
    }
    public boolean hasSubDirs() {
        File[] files = listFiles();
        if (files == null)
            return false;
        for (int k=0; k<files.length; k++) {
            if (files[k].isDirectory())
                return true;
        }
        return false;
    }
    public int compareTo(FileNode toCompare) {
        return  m_file.getName().compareToIgnoreCase(
            toCompare.m_file.getName() );
    }
    protected File[] listFiles() {
        if (!m_file.isDirectory())
            return null;
        try {
            return m_file.listFiles();
        }
        catch (Exception ex) {
            return null;
        }
    }
}
```

mfg
pabu


----------



## SuperSeppel13 (4. Jan 2010)

Der "listFiles"-Methode der Klasse File kannst du einen File(name)Filter übergeben. Schreib einfach einen Filter, der bloß die gewünschten Formate akzeptiert.


----------



## pabu1983 (4. Jan 2010)

Hast du auch einen Codeschnipsel wie der File(name)Filter aussehen muss? Höre das zum ersten mal  Muss mich mal über google einlesen...


----------



## SuperSeppel13 (4. Jan 2010)

Ein Filter für txt-Dateien könnte eventuell so aussehen:


```
folder.listFiles(new FileFilter() {
    public boolean accept(File f) {
        if(f.isDirectory())
            return false;

        String name = f.getName();
        String extension = name.substring(name.lastIndexOf(".")+1);
        //System.out.println(name + "; " + extension);
        return extension.equals("txt");
    }
});
```


----------



## Arbon (4. Jan 2010)

Anstatt die Extension herauszufiltern sollte eigentlich auch das reichen:

```
folder.listFiles(new FileFilter() {
@Override
		public boolean accept(File f) {
		        if(f.isDirectory())
			       return false;
			return f.getAbsolutePath().endsWith(".txt");
		}
});
```


----------



## Michael... (4. Jan 2010)

Wenn's nicht unbedingt was eigenes sein soll kann man auch den JFileChooser hernehmen, hier kann man ebenfalls die Dateiauswahl per Filter einschränken.


----------



## SuperSeppel13 (4. Jan 2010)

Naja, der JFileChooser ist jetzt nicht so geeignet um ein TreeModel daraus zu basteln und ich hatte mir überlegt, die Dateiendung herauszufiltern um sie dann mit einer Liste zugelassener Endungen zu vergleichen. Wenn es eh bloß ein oder zwei formate sind, ist es mit endsWith(...) wohl einfacher.


----------



## pabu1983 (5. Jan 2010)

Ja das mit dem FileChooser ist wirklich nicht so praktisch für meinen Fall.
Danke euch für eure Antworten, werde jetzt versuchen das in meinen Quelltext einzubauen.
Hoffentlich reichen hierfür meine Java-Kenntnisse (*gespannt bin*)

[EDIT]: Also ich hab jetzt mal alles so eingebaut und das Problem ist was sich jetzt ergibt das wenn ich auf die Laufwerke klicke, öffnet sich nichts (als ob die Laufwerke leer sind). Ich hab auch schon Dateien mit der entsprechenden Endung direkt ins laufwerk gelegt (z.B. direkt in C:\) hilft nix


----------



## SuperSeppel13 (5. Jan 2010)

Naja, also wenn du den FileFilter genau so übernaommen hast, wie in unseren Beispielen, dann filtert der halt auch alle Ordner heraus. Warum allerdings auch dateien direkt im entsprechenden laufwerk nicht angezeigt werden, kann ich so auch nicht sagen.
Da müsstest du nochmal deinen code posten.


----------



## pabu1983 (6. Jan 2010)

Ok also hier der Code mit der Version von euch. Wenn ich das so ausführe passiert das wie oben erwähnt und in den Bildern dargestellt wird.


```
import java.awt.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
import javax.swing.tree.*;
import javax.swing.event.*;

public class DirTree extends JScrollPane {
    public static final ImageIcon ICON_COMPUTER = new ImageIcon("D:/Projekte/2009-11/Java_GUI/Conti_Tree/Icons/monitor.png");
    public static final ImageIcon ICON_DISK = new ImageIcon("D:/Projekte/2009-11/Java_GUI/Conti_Tree/Icons/festplatte.png");
    public static final ImageIcon ICON_FOLDER = new ImageIcon("D:/Projekte/2009-11/Java_GUI/Conti_Tree/Icons/ordner_zu.png");
    public static final ImageIcon ICON_EXPANDEDFOLDER = new ImageIcon("D:/Projekte/2009-11/Java_GUI/Conti_Tree/Icons/ordner_auf.png");
    protected JTree m_tree;
    protected DefaultTreeModel m_model;

    public DirTree() {
        super();
        DefaultMutableTreeNode top = new DefaultMutableTreeNode(new IconData(ICON_COMPUTER, null, "Computer"));
        DefaultMutableTreeNode node;
        
        File[] roots = File.listRoots();                                        // START - Befüllung des Baumes
        for (int k=0; k<roots.length; k++) {                                    // Es werden alle Laufwerke
            node = new DefaultMutableTreeNode(new IconData(ICON_DISK,           // eingelesen die generell
                null, new FileNode(roots[k])));                                 // an diesem Rechner verfügbar
            top.add(node);                                                      // sind und in den Baum
            node.add(new DefaultMutableTreeNode(new Boolean(true)));            // eingefügt
        }                                                                       // ENDE - Befüllung des Baumes

//        try {
//            UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
//        }
//        catch (Exception e) {
//            e.printStackTrace();
//        }

        m_model = new DefaultTreeModel(top);
        m_tree = new JTree(m_model);
        m_tree.putClientProperty("JTree.lineStyle", "Angled");
        IconCellRenderer renderer = new IconCellRenderer();
        m_tree.setCellRenderer(renderer);
        m_tree.addTreeExpansionListener(new DirExpansionListener());
        m_tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
        m_tree.setShowsRootHandles(true);
        m_tree.setEditable(false);

        this.getViewport().add(m_tree);
    }
    DefaultMutableTreeNode getTreeNode(TreePath path) {
        return (DefaultMutableTreeNode)(path.getLastPathComponent());
    }
    FileNode getFileNode(DefaultMutableTreeNode node) {
        if (node == null)
            return null;
        Object obj = node.getUserObject();
        if (obj instanceof IconData)
            obj = ((IconData)obj).getObject();
        if (obj instanceof FileNode)
            return (FileNode)obj;
        else
            return null;
    }
    // Make sure expansion is threaded and updating the tree model
    // only occurs within the event dispatching thread.
    class DirExpansionListener implements TreeExpansionListener {
        public void treeExpanded(TreeExpansionEvent event) {
            final DefaultMutableTreeNode node = getTreeNode(
                event.getPath());
            final FileNode fnode = getFileNode(node);
            Thread runner = new Thread() {
                public void run() {
                    if (fnode != null && fnode.expand(node)) {
                        Runnable runnable = new Runnable() {
                            public void run() {
                                m_model.reload(node);
                            }
                        };
                        SwingUtilities.invokeLater(runnable);
                    }
                }
            };
            runner.start();
        }
        public void treeCollapsed(TreeExpansionEvent event) {}
    }

    public static void main(String argv[]) {
        JFrame frame = new JFrame();
        DirTree scrollTree = new DirTree();
        frame.setSize(200,300);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(scrollTree);
        frame.setVisible(true);
    }
}

class IconCellRenderer extends DefaultTreeCellRenderer {
    public IconCellRenderer() {
        setLeafIcon(null);
        setOpenIcon(null);
    }
    public Component getTreeCellRendererComponent(JTree tree,
        Object value, boolean sel, boolean expanded, boolean leaf,
        int row, boolean hasFocus) {
        // Invoke default implementation
        Component result = super.getTreeCellRendererComponent(tree,
            value, sel, expanded, leaf, row, hasFocus);
        DefaultMutableTreeNode node = (DefaultMutableTreeNode)value;
        Object obj = node.getUserObject();
        setText(obj.toString());
        if (obj instanceof Boolean)
            setText("Retrieving data...");
        if (obj instanceof IconData) {
            IconData idata = (IconData)obj;
            if (expanded)
                setIcon(idata.getExpandedIcon());
            else
                setIcon(idata.getIcon());
        }
        else
            setIcon(null);
        return result;
    }
}

class IconData {
    protected Icon   m_icon;
    protected Icon   m_expandedIcon;
    protected Object m_data;
    public IconData(Icon icon, Object data) {
        m_icon = icon;
        m_expandedIcon = null;
        m_data = data;
    }
    public IconData(Icon icon, Icon expandedIcon, Object data) {
        m_icon = icon;
        m_expandedIcon = expandedIcon;
        m_data = data;
    }
    public Icon getIcon() {
        return m_icon;
    }
    public Icon getExpandedIcon() {
        return m_expandedIcon!=null ? m_expandedIcon : m_icon;
    }
    public Object getObject() {
        return m_data;
    }
    public String toString() {
        return m_data.toString();
    }
}

class FileNode {
    protected File m_file;
    public FileNode(File file) {
        m_file = file;
    }
    public File getFile() {
        return m_file;
    }
    public String toString() {
        return m_file.getName().length() > 0 ? m_file.getName() :
            m_file.getPath();
    }

    // Alternatively we copud sub-class TreeNode
    public boolean expand(DefaultMutableTreeNode parent) {
        DefaultMutableTreeNode flag = (DefaultMutableTreeNode)parent.getFirstChild();
        if (flag==null)   // No flag
            return false;
        Object obj = flag.getUserObject();
        if (!(obj instanceof Boolean))
            return false;      // Already expanded
        parent.removeAllChildren();  // Remove Flag
        File[] files = listFiles();
        if (files == null)
            return true;
        Vector v = new Vector();
        for (int k=0; k<files.length; k++) {
            File f = files[k];
            if (!(f.isDirectory()))
                continue;
            FileNode newNode = new FileNode(f);
            boolean isAdded = false;
            for (int i=0; i<v.size(); i++) {
                FileNode nd = (FileNode)v.elementAt(i);
                if (newNode.compareTo(nd) < 0) {
                    v.insertElementAt(newNode, i);
                    isAdded = true;
                    break;
                }
            }
            if (!isAdded)
                v.addElement(newNode);
        }
        for (int i=0; i<v.size(); i++) {
            FileNode nd = (FileNode)v.elementAt(i);
            IconData idata = new IconData(DirTree.ICON_FOLDER,
                DirTree.ICON_EXPANDEDFOLDER, nd);
            DefaultMutableTreeNode node = new
                DefaultMutableTreeNode(idata);
            parent.add(node);
            if (nd.hasSubDirs())
                node.add(new DefaultMutableTreeNode(
                    new Boolean(true) ));
        }
        return true;
    }
    public boolean hasSubDirs() {
        File[] files = listFiles();
        if (files == null)
            return false;
        for (int k=0; k<files.length; k++) {
            if (files[k].isDirectory())
                return true;
        }
        return false;
    }
    public int compareTo(FileNode toCompare) {
        return  m_file.getName().compareToIgnoreCase(
            toCompare.m_file.getName() );
    }

        protected File[] listFiles() {
        if (!m_file.isDirectory())
            return null;
        try {
            return m_file.listFiles(new FileFilter() {
                public boolean accept(File f) {
                    if(f.isDirectory())
                        return false;
                    String name = f.getName();
                    String extension = name.substring(name.lastIndexOf(".")+1);
                    //System.out.println(name + "; " + extension);
                    return extension.equals("txt");
                }
            });
        }
        catch (Exception ex) {
            return null;
        }
    }
}
```


----------



## SuperSeppel13 (6. Jan 2010)

Also ich habe mir jetzt nich die mühe gemacht, deinen ganzen quelltext nachzuvollziehen, aber der FileFilter funktioniert hervorragend.
Wenn du willst, dass auch Ordner angezeigt werden, musst du natürlich, wenn das "File" ein ordner ist, true und nicht false wiedergeben. Aber selbst wenn du alle arten von dateien akzeptierst, werden in dem tree keine dateien angezeigt. Das liegt also an der art, wie du die daten verarbeitest.

Noch ein Hinweis: im moment erzeugst du noch bei jedem aufruf von listFiles() einen neuen FileFilter. Besser wäre es, in FileNode FileFilter zu implementieren:

```
class FileNode implements FileFilter{

    // all deine Felder und Methoden...    

    protected File[] listFiles() {
        if (!m_file.isDirectory()) {
            return null;
        }
        try {
            return m_file.listFiles(this);
        } catch (Exception ex) {
            return null;
        }
    }
    
    public boolean accept(File f) {
        if (f.isDirectory()) 
            return true;
        
        String name = f.getName();
        String extension = name.substring(name.lastIndexOf(".") + 1);
        System.out.println(name + " -> " + extension.toLowerCase().equals("jpg"));//um zu sehen, welche dateien akzeptiert werden
        return extension.toLowerCase().equals("jpg");
    }
}
```


----------



## pabu1983 (7. Jan 2010)

...


----------



## pabu1983 (7. Jan 2010)

So also ich hab jetzt meine Quellcode soweit das ich weiß wo was geändert werden muss, allerdings kenn ich die Befehle nicht. Erst mal mein aktueller Quellcode:


```
import java.awt.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
import javax.swing.tree.*;
import javax.swing.event.*;

public class DirTree extends JScrollPane {
    public static final ImageIcon ICON_COMPUTER = new ImageIcon("D:/Projekte/2009-11/Java_GUI/Conti_Tree/Icons/monitor.png");
    public static final ImageIcon ICON_DISK = new ImageIcon("D:/Projekte/2009-11/Java_GUI/Conti_Tree/Icons/festplatte.png");
    public static final ImageIcon ICON_FOLDER = new ImageIcon("D:/Projekte/2009-11/Java_GUI/Conti_Tree/Icons/ordner_zu.png");
    public static final ImageIcon ICON_EXPANDEDFOLDER = new ImageIcon("D:/Projekte/2009-11/Java_GUI/Conti_Tree/Icons/ordner_auf.png");
    public static final ImageIcon ICON_TXT = new ImageIcon("D:/Projekte/2009-11/Java_GUI/Conti_Tree/Icons/datei_txt.png");
    public static final ImageIcon ICON_JPG = new ImageIcon("D:/Projekte/2009-11/Java_GUI/Conti_Tree/Icons/datei_jpg.png");
    public static final ImageIcon ICON_PNG = new ImageIcon("D:/Projekte/2009-11/Java_GUI/Conti_Tree/Icons/datei_png.png");
    protected JTree m_tree;
    protected DefaultTreeModel m_model;

    public DirTree() {
        super();
        DefaultMutableTreeNode top = new DefaultMutableTreeNode(new IconData(ICON_COMPUTER, null, "Computer"));
        DefaultMutableTreeNode node;
        
        File[] roots = File.listRoots();                                        // START - Befüllung des Baumes
        for (int k=0; k<roots.length; k++) {                                    // Es werden alle Laufwerke
            node = new DefaultMutableTreeNode(new IconData(ICON_DISK,           // eingelesen die generell
                null, new FileNode(roots[k])));                                 // an diesem Rechner verfügbar
            top.add(node);                                                      // sind und in den Baum
            node.add(new DefaultMutableTreeNode(new Boolean(true)));            // eingefügt
        }                                                                       // ENDE - Befüllung des Baumes

//        try {
//            UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
//        }
//        catch (Exception e) {
//            e.printStackTrace();
//        }

        m_model = new DefaultTreeModel(top);
        m_tree = new JTree(m_model);
        m_tree.putClientProperty("JTree.lineStyle", "Angled");
        IconCellRenderer renderer = new IconCellRenderer();
        m_tree.setCellRenderer(renderer);
        m_tree.addTreeExpansionListener(new DirExpansionListener());
        m_tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
        m_tree.setShowsRootHandles(true);
        m_tree.setEditable(false);


        this.getViewport().add(m_tree);
    }
    DefaultMutableTreeNode getTreeNode(TreePath path) {
        return (DefaultMutableTreeNode)(path.getLastPathComponent());
    }
    FileNode getFileNode(DefaultMutableTreeNode node) {
        if (node == null)
            return null;
        Object obj = node.getUserObject();
        if (obj instanceof IconData)
            obj = ((IconData)obj).getObject();
        if (obj instanceof FileNode)
            return (FileNode)obj;
        else
            return null;
    }
    // Make sure expansion is threaded and updating the tree model
    // only occurs within the event dispatching thread.
    class DirExpansionListener implements TreeExpansionListener {
        public void treeExpanded(TreeExpansionEvent event) {
            final DefaultMutableTreeNode node = getTreeNode(
                event.getPath());
            final FileNode fnode = getFileNode(node);
            Thread runner = new Thread() {
                public void run() {
                    if (fnode != null && fnode.expand(node)) {
                        Runnable runnable = new Runnable() {
                            public void run() {
                                m_model.reload(node);
                            }
                        };
                        SwingUtilities.invokeLater(runnable);
                    }
                }
            };
            runner.start();
        }
        public void treeCollapsed(TreeExpansionEvent event) {}
    }

    public static void main(String argv[]) {
        JFrame frame = new JFrame();
        DirTree scrollTree = new DirTree();
        frame.setSize(200,300);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(scrollTree);
        frame.setVisible(true);
    }
}

class IconCellRenderer extends DefaultTreeCellRenderer {
    public IconCellRenderer() {
        setLeafIcon(null);
        setOpenIcon(null);
    }
    public Component getTreeCellRendererComponent(JTree tree,
        Object value, boolean sel, boolean expanded, boolean leaf,
        int row, boolean hasFocus) {
        // Invoke default implementation
        Component result = super.getTreeCellRendererComponent(tree,
            value, sel, expanded, leaf, row, hasFocus);
        DefaultMutableTreeNode node = (DefaultMutableTreeNode)value;
        Object obj = node.getUserObject();
        setText(obj.toString());
        if (obj instanceof Boolean)
            setText("Retrieving data...");
        if (obj instanceof IconData) {
            IconData idata = (IconData)obj;
            if (expanded)
                setIcon(idata.getExpandedIcon());
            else
                setIcon(idata.getIcon());
        }
        else
            setIcon(null);
        return result;
    }
}

class IconData {
    protected Icon   m_icon;
    protected Icon   m_expandedIcon;
    protected Object m_data;
    public IconData(Icon icon, Object data) {
        m_icon = icon;
        m_expandedIcon = null;
        m_data = data;
    }
    public IconData(Icon icon, Icon expandedIcon, Object data) {
        m_icon = icon;
        m_expandedIcon = expandedIcon;
        m_data = data;
    }
    public Icon getIcon() {
        return m_icon;
    }
    public Icon getExpandedIcon() {
        return m_expandedIcon!=null ? m_expandedIcon : m_icon;
    }
    public Object getObject() {
        return m_data;
    }
    public String toString() {
        return m_data.toString();
    }
}

class FileNode {
    protected File m_file;
    public FileNode(File file) {
        m_file = file;
    }
    public File getFile() {
        return m_file;
    }
    public String toString() {
        return m_file.getName().length() > 0 ? m_file.getName() :
            m_file.getPath();
    }

    // Alternatively we copud sub-class TreeNode
    public boolean expand(DefaultMutableTreeNode parent) {
        DefaultMutableTreeNode flag = (DefaultMutableTreeNode)parent.getFirstChild();
        if (flag==null)   // No flag
            return false;
        Object obj = flag.getUserObject();
        if (!(obj instanceof Boolean))
            return false;      // Already expanded
        parent.removeAllChildren();  // Remove Flag
        File[] files = listFiles();
        if (files == null)
            return true;
        Vector v = new Vector();
        for (int k=0; k<files.length; k++) {
            File f = files[k];
            
//            if (!(f.isDirectory()))       // NUR ORDNER ANZEIGEN!!!
  // HIER NOCH EINFÜGEN DAS ANDERE ICONS VERWENDET WERDEN!!!!!
//                continue;                 // NUR ORDNER ANZEIGEN!!!

            FileNode newNode = new FileNode(f);
            boolean isAdded = false;
            for (int i=0; i<v.size(); i++) {
                FileNode nd = (FileNode)v.elementAt(i);
                if (newNode.compareTo(nd) < 0) {
                    v.insertElementAt(newNode, i);
                    isAdded = true;
                    break;
                }
            }
            if (!isAdded)
                v.addElement(newNode);
        }
        for (int i=0; i<v.size(); i++) {
            FileNode nd = (FileNode)v.elementAt(i);
            IconData idata = new IconData(DirTree.ICON_FOLDER,
                DirTree.ICON_EXPANDEDFOLDER, nd);
            DefaultMutableTreeNode node = new
                DefaultMutableTreeNode(idata);
            parent.add(node);
            if (nd.hasSubDirs())
                node.add(new DefaultMutableTreeNode(
                    new Boolean(true) ));
        }
        return true;
    }
    public boolean hasSubDirs() {
        File[] files = listFiles();
        if (files == null)
            return false;
        for (int k=0; k<files.length; k++) {
            if (files[k].isDirectory())
                return true;
        }
        return false;
    }
    public int compareTo(FileNode toCompare) {
        return  m_file.getName().compareToIgnoreCase(
            toCompare.m_file.getName() );
    }
    
        protected File[] listFiles() {
        if (!m_file.isDirectory())
            return null;
        try {
            return m_file.listFiles(new FileFilter() {
                public boolean accept(File f) {
                    if(f.isDirectory())
                        // Durchsuche den Ordner auf txt/jpg/png
                        return true;
                    String name = f.getName();
                    String extension = name.substring(name.lastIndexOf(".")+1);
                    //System.out.println(name + "; " + extension);
                    return extension.equals("txt") || extension.equals("jpg") || extension.equals("png");
                }
            });
        }
        catch (Exception ex) {
            return null;
        }
    }

}
```

Jetzt will ich noch zwei Dinge ändern. Ich glaube das erste kann ich in der Expand-Methode ändern da wo ich folgendes stehen habe:

```
//            if (!(f.isDirectory()))       // NUR ORDNER ANZEIGEN!!!
  // HIER NOCH EINFÜGEN DAS ANDERE ICONS VERWENDET WERDEN!!!!!
//                continue;                 // NUR ORDNER ANZEIGEN!!!
```

Wie kann ich an dieser Stelle sagen das er für alle Dateien (also Blätter) die die Endung "txt" haben, dass am Beginn des Quellcodes definierte ImageIcon ICON_TXT nehmen soll? Und das auch für "jpg" und "png"?

Und das zweite werde ich wohl am schluss vom quelltext ändern müssen:

```
try {
            return m_file.listFiles(new FileFilter() {
                public boolean accept(File f) {
                    if(f.isDirectory())
                        // Durchsuche den Ordner auf txt/jpg/png
                        return true;
                    String name = f.getName();
                    String extension = name.substring(name.lastIndexOf(".")+1);
                    //System.out.println(name + "; " + extension);
                    return extension.equals("txt") || extension.equals("jpg") || extension.equals("png");
                }
            });
        }
```

Und zwar will ich das er auch in Unterordner nach diesen Dateiendungen sucht und wenn eine dieser vorhanden ist ein true ansonsten ein false zurückliefert. Soll auch mit Unter-Unter-Unterordner möglich sein (usw.)

Danke für eure Hilfe, ich versuch natürlich nebenbei das auch selbst hinzubekommen...


----------



## SuperSeppel13 (7. Jan 2010)

Nimms mir nicht übel, dass ich jetzt keine Zeit habe, konkrete implementierungen zu basteln, aber hier ein paar anregungen:

Erweitere FileNode dahingehend, dass jedes Objekt der Klasse den Typ des Files (Ordner/txt/png/...) enthält und erzeuge dann für jede der entsprechenden Dateien einen neuen FileNode, wie du es auch schon mit den Ordnern tust.
Dann musst du nurnoch deinen TreeCellRenderer ändern, sodass er zu jedem typ das entsprechende Icon zeichnet.

Wenn du willst, dass dein FileFilter nur alle die Ordner durchlässt, die (in irgendeinem unterordner) eine txt beinhalten, müsstest du beim aufklappen einer Festplatte erstmal die GESAMTE platte durchsuchen. Das dauert!!! Ich glaube nicht, dass du das wirklich willst... 
Da ist es (glaube ich) besser, alle ordner anzuzeigen, auch wenn man dann womöglich nach dem aufklappen eines ordners feststellen muss, dass er keine txts enthält.


----------



## pabu1983 (8. Jan 2010)

ja ne versteh ich seppel, ich will es ja auch selbst hinbekommen. Danke für deine Tips, werd mich mal versuchen das hinzubekommen...aber wenn du mal die Muse haben solltest, kannste gern etwas Quelltext zusammenhäääcken


----------



## pabu1983 (8. Jan 2010)

Also das mit den Icons hab ich so versucht

```
public IconCellRenderer(File dat) {
        String name = dat.getName();
        String extension = name.substring(name.lastIndexOf(".")+1);
        if (extension.equals("aus"))
            setLeafIcon(DirTree.ICON_AUS);
        if (extension.equals("dl2"))
            setLeafIcon(DirTree.ICON_DL2);
        if (extension.equals("dl3"))
            setLeafIcon(DirTree.ICON_DL3);
        setOpenIcon(null);
    }
```

Aber dann kommt im Netbeans ein Fehler oben im public DirTree() bei:

```
IconCellRenderer renderer = new IconCellRenderer();
```

Cannot find symbol constructor IconCellRenderer. Das liegt ja daran das ich ja File übergeben muss, aber ich weiß nicht welches 
Ich glaub so langsam ich programmier in die falsche Richtung


----------



## SuperSeppel13 (8. Jan 2010)

Hm, da gehst du wirklich etwas in die falsche richtung...
Du kannst natürlich deinem IconCellRenderer im Konstruktor nicht das Icon für jeden TreeNode übergeben.
Eigentlich kann dein IconCellRenderer schon alles, du musst bloß das richtige Icon in dem IconData-Objekt übergeben.
Ich habe dir hier nochmal was gebastelt:
 - In "FileNode.expand(...)", wo vorher mit Dateien nichts gemacht wurde, wird hier eine zweite Liste (Vector) für diese angelegt [kleiner Tipp: mit "Vector<FileNode>" kannst du direkt angeben, dass der Vector nur FileNodes enthält - erspart das TypeCasting].
 - Die beiden Listen werden dann nacheinander (erst ordner, dann dateien) dem parent node hinzugefügt.
 - ich habe deine hasSubDirs-Methode geändert, sodass auch FileNodes von Ordnern, die zwar keine Unterprdner, allerdings weitere relevante Dateien enthalten, das flag erhalten und somit expandable werden.

hier der code:

```
public boolean expand(DefaultMutableTreeNode parent) {
        // flag checking...
        DefaultMutableTreeNode flag = (DefaultMutableTreeNode) parent.getFirstChild();
        if (flag == null) // No flag
        {
            return false;
        }
        Object obj = flag.getUserObject();
        if (!(obj instanceof Boolean)) {
            return false;      // Already expanded
        }
        parent.removeAllChildren();  // Remove Flag
        File[] files = listFiles();
        if (files == null) {
            return true;
        }

        // Datei- unf Ordnerlisten erstellen
        Vector<FileNode> dirs = new Vector<FileNode>();//liste der Ordner
        Vector<FileNode> leafs = new Vector<FileNode>();//Liste der Dateien
        Vector<FileNode> v;
        for (int k = 0; k < files.length; k++) {
            File f = files[k];
            if (f.isDirectory()){
                v = dirs;
            } else {
                v = leafs;
            }

            FileNode newNode = new FileNode(f);
            boolean isAdded = false;
            for (int i = 0; i < v.size(); i++) {
                if (newNode.compareTo(v.elementAt(i)) < 0) {
                    v.insertElementAt(newNode, i);
                    isAdded = true;
                    break;
                }
            }
            if (!isAdded) {
                v.addElement(newNode);
            }
        }

        // alle ordner hinzufügen
        for (int i = 0; i < dirs.size(); i++) {
            FileNode nd = (FileNode) dirs.elementAt(i);
            IconData idata = new IconData(DirTree.ICON_FOLDER,
                    DirTree.ICON_EXPANDEDFOLDER, nd);
            DefaultMutableTreeNode node = new DefaultMutableTreeNode(idata);
            parent.add(node);

            if (!nd.isLeaf()) {
                node.add(new DefaultMutableTreeNode(
                        new Boolean(true)));
            }
        }

        // alle dateien hinzufügen
        for (int i = 0; i < leafs.size(); i++) {
            FileNode nd = leafs.elementAt(i);
            // hier evtl dateityp von "nd.m_file" überprüfen und dann
            IconData idata = new IconData(DirTree.ICON_TXT, // hier das entsprechende Icon übergeben
                    DirTree.ICON_EXPANDEDFOLDER, nd);
            DefaultMutableTreeNode node = new DefaultMutableTreeNode(idata);
            parent.add(node);
        }
        return true;
    }

    public boolean isLeaf() { // ehemals "hasSubDirs"
        File[] files = listFiles();
        return files == null || files.length == 0;
    }
```

Ich hoffe, das hilft dir weiter.
Viel Erfolg damit!


----------



## pabu1983 (8. Jan 2010)

Hey super seppel!!! DANKE!!! Das funktioniet echt super! Jetzt versuch ich mal ob ich das allein hinbekomme mit den drei verschiedenen Endungen = verschiedene Icons...

JUHU!! Geschafft!!! NOCHMALS DANKE AN ALLE!!!!!!!!


----------

