Dateibaum
Die Klasse DateiBaum
erweitert JFrame
,
stellt das GUI bereit und enthält die Main-Methode. Dem
Konstruktor wird dort als Parameter der absoluten Pfad des
Wurzelverzeichnisses übergeben. Im vorliegenden Fall ist dies
das Heimatverzeichnis des Nutzers.
Innerhalb des Konstruktors
wird der Pfad an die Methode createModel()
weitergereicht. Sie erzeugt ein DefaultTreeModel
, das
den Inhalt des Baums verwaltet. Das Model selbst wird bei der
Erzeugung des JTree
an dessen Konstruktor
übergeben und der JTree
auf ein JScrollPane
gesetzt. Vorher wird der JTree
noch bei einem TreeExpansionListener
angemeldet. Er ist als anonyme Klasse realisiert, in der nur die
Methode treeExpanded()
überschrieben wird. Sie
führt folgendes aus:
Wird ein Baumknoten angeklickt, so wird der Pfad zum Knoten als TreePath
-Objekt und dessen letztes Element als FNode
-Objekt
ermittelt. Hierbei handelt es sich um eine Erweiterng eines DefaultMutableTreeNode
, der zweiten im Beispiel deklarierten Klasse. Sie
repräsentiert einen Baumknoten. Mehr dazu weiter
unten.
Abschließend wird ein Panel mit Radio-Buttons
unten auf den Frame gesetzt und desser Erscheinung auf die
übliche Weise fertig konfiguriert.
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import javax.swing.ButtonGroup;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeExpansionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
public class DateiBaum extends JFrame {
public final static int SHOW_ALL = 0;
public final static int SHOW_HIDDEN = 1;
public final static int SHOW_VISIBLE = -1;
private String path;
private int showType = SHOW_VISIBLE;
private JTree tree;
public DateiBaum(String path) {
this.path = path;
tree = new JTree(createModel(this.path));
tree.addTreeExpansionListener(new TreeExpansionListener() {
public void treeExpanded(TreeExpansionEvent event) {
TreePath path = event.getPath();
FNode node = (FNode) path.getLastPathComponent();
DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
node.addFiles(showType);
model.nodeStructureChanged(node);
}
public void treeCollapsed(TreeExpansionEvent event) {
}
});
JScrollPane sPane = new JScrollPane(tree);
this.add(sPane, BorderLayout.CENTER);
this.add(createButtPanel(), BorderLayout.SOUTH);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.pack();
this.setLocationRelativeTo(null);
this.setTitle("Datei-Browser");
this.setVisible(true);
}
private DefaultTreeModel createModel(String path) {
File root = new File(path);
FNode rootNode = new FNode(root);
rootNode.addFiles(showType);
return new DefaultTreeModel(rootNode);
}
private JPanel createButtPanel() {
JPanel panel = new JPanel(new FlowLayout());
JRadioButton allButt = new JRadioButton("Alle");
allButt.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
showType = SHOW_ALL;
tree.setModel(createModel(path));
}
});
JRadioButton hiddenButt = new JRadioButton("Versteckt");
hiddenButt.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
showType = SHOW_HIDDEN;
tree.setModel(createModel(path));
}
});
JRadioButton visibleButt = new JRadioButton("Sichtbar", true);
visibleButt.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
showType = SHOW_VISIBLE;
tree.setModel(createModel(path));
}
});
ButtonGroup group = new ButtonGroup();
group.add(allButt);
group.add(hiddenButt);
group.add(visibleButt);
panel.add(allButt);
panel.add(hiddenButt);
panel.add(visibleButt);
return panel;
}
public void setPath(String path) {
this.path = path;
}
public static void main(String[] args) {
new DateiBaum(System.getProperty("user.home"));
}
}
class FNode extends DefaultMutableTreeNode {
public FNode(File file) {
setUserObject(file);
}
public File getFile() {
return (File) getUserObject();
}
public boolean getAllowsChildren() {
return getFile().isDirectory();
}
public boolean isLeaf() {
return !getFile().isDirectory();
}
public String toString() {
return getFile().getName();
}
public void addFiles(int showHidden) {
File[] files = getFile().listFiles();
for (File f : files) {
if (showHidden == DateiBaum.SHOW_HIDDEN) {
if (f.isHidden())
this.add(new FNode(f));
} else if (showHidden == DateiBaum.SHOW_VISIBLE) {
if (!f.isHidden())
this.add(new FNode(f));
} else {
this.add(new FNode(f));
}
}
}
}
Die Klasse FNode
erweitert DefaultMutableTreeNode
, die ihrerseits einen Baumknoten mit 0 - n Kindknoten darstellt.
Innerhalb eines Dateibaums wird hierdurch somit also eine Datei oder
ein Verzeichnis repräsentiert. Der Konstruktor bekommt ein File
-Objekt übergeben, das als sog. UserObject gesetzt
wird. Als UserObject wird ein Object
bezeichnet, das die durch den Nutzer spezifizierten Daten eines
Baumknotens darstellt. In einem Dateibaum ist dies natürlich
ein File
-Objekt. Um es als Baumknoten zu
spezifizieren, muss geklärt werden, ob es - als Verzeichnis -
weitere File
-Objekte enthalten kann oder nicht. Hierzu
werden die beiden Methoden isLeaf()
und getAllowsChildren()
entsprechend überschrieben.
Eine weitere Methode muss erwähnt werden: addFiles()
bekommt einen int
-Parameter übergeben, mit dem
entschieden werden kann, welcher Sichtbarkeitsstatus im Baum
dargestellt werden soll. Hierzu wird zunächst der Inhalt des
aktuellen UserObject als Array ermittelt. Es enthält die File
-Objekte des Baumknotens, sofern dieser ein Verzeichnis ist. Das
Array wird durchlaufen und jedes einzelne Element dem
übergebenen Parameter gemäß überprüft und
je nach Ergebnis (sichtbar, nichtsichbar oder beides) dem aktuellen
UserObject hinzugefügt.
Die Methode wird an zwei Stellen
aufgerufen: zum einen bei der initialen Generierung des TreeModel
und zum zweiten in der Methode TreeExpansionListener#treeExpanded()
, die jedesmal angesprochen wird, wenn ein Knoten des Baumes
expandiert wird.