Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden. Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
Hallo, hab folgendes Problem...
Wie kann man bestimmte Knoten im JTree aus- und wieder einblenden?
Habe es in meinem TreeRendere schonmal mit setVisible() versucht, aber irgendwie scheint das meine Nodes nicht zu interessieren...
Hier mal mein TreeRenderer...
Code:
public MovieTreeRenderer()
{
super();
}
public Component getTreeCellRendererComponent(JTree tree,Object value,boolean sel,boolean expanded,boolean leaf,int row,boolean hasFocus)
{
super.getTreeCellRendererComponent(tree,value,sel,expanded,leaf,row,hasFocus);
String av = value.toString();
if (leaf==true)
{
if (av.endsWith(" 0"))
{
setIcon(avail);
}
else
{
setIcon(notavail);
setForeground(Color.red);
}
}
if (av.startsWith("Geliefert"))
{
setIcon(infos);
setForeground(Color.blue);
}
setClosedIcon(null);
setOpenIcon(null);
return this;
zur Info... Durch den value Text kann ich eindeutig bestimmen welches Icon davor muß, deswegen die ganzen av.startswith(..) und av.endwith(..)....
Hallo, hab folgendes Problem...
Wie kann man bestimmte Knoten im JTree aus- und wieder einblenden?
Habe es in meinem TreeRendere schonmal mit setVisible() versucht, aber irgendwie scheint das meine Nodes nicht zu interessieren...
Hier mal mein TreeRenderer....
Du baust dir ein TableModel, dass alle deine Daten enthält. Ein weiteres TableModel greift auf dieses dann zu und rechnet Indices, etc. um, um nur das anzuzeigen, was angezeigt werden soll. Das Model muss zudem TreeModelListener implementieren und am Haupt-Model lauschen, die Events passend umrechnen und an die eigenen Listener (den JTree) weitergeben.
Ich habe sowas hier auch schon ein paar Wochen laufen. Aller Anfang war schwer, hinterhere hab ich mich aber gefragt, wo da jetzt das Problem war
Jo, danke Al... Nach meinem Post gestern nacht hab ich deinen Thread dann auch noch gefunden :roll:
So ganz raus hab ichs noch nciht, aber im moment ist da größere problem das wenn ich alles in ne .jar datei packe das er mir den tree garnicht anzeigt... aber naja... mal schaun...
Du baust dir ein TableModel, dass alle deine Daten enthält. Ein weiteres TableModel greift auf dieses dann zu und rechnet Indices, etc. um, um nur das anzuzeigen, was angezeigt werden soll. Das Model muss zudem TreeModelListener implementieren und am Haupt-Model lauschen, die Events passend umrechnen und an die eigenen Listener (den JTree) weitergeben.
Ah, oh.. großes SORRY! Ich meinte natürlich TreeModel, auch wenn ich TableModel geschrieben habe. Mea culpa
Ich habe in meiner Anwendung eine Erweiterung des JTrees, der auf ein eigenes TableModel zugreift, welches im Grunde nur als Filter agiert und als Datenquelle ein weiteres TableModel nutzt.
Änderungen an den Daten (Änderungen im Node, Node hinzufügen, Node löschen, Struktur ändern) werden nach unten durchgereicht. Dort wird dann der passende Evbent erzeugt, der dann nach oben durchgereicht und dabei in MyFilter für MyTree passend umgerechnet wird. Lesezugriffe gehen durch den Filter.
So habe ich eine Anwendung realisiert (bzw. ich sehe zu sie bis zur Messe präsentationsfähig zu bekommen) wo ich mit verschiendenen Trees und Filtern unterschiedliche Teile derselben Daten anzeige.
Auf ne allgemeine Anwendung übertragen könnte man so z.B. einen Datei-Explorer realsieren, der wahlweise nur TXT-Dateien oder so anzeigt...
Der Grundgedanke (mit dem sog. delegate) ist universell für alle MVC-Strukturen verwendbar.
So, ich nochmal, das mit dem anzeigen hab ich gelöst (mir fehle ein Image in dem .jar File) dumdidum...
Aber das mit dem Model hab ich noch nicht so ganz....
Ich muß halt nur die Blätter ausblenden falls nötig... gesteuert werden solls über die Menüleiste des Desktops in Form einer CheckBox...
Hast vielleicht nen CodeSchnipsel für dieses TreeModel?
wei gesagt, blicke durch deinen anderen thread nich ganz durch, sorry.
Also deine Version wäre noch eine Erweiterung von meiner, da meine TreeFilter (so nenne ich die) nicht volldynamisch arbeiten. Ich habe im Programm unterschiedliche Ansihten (JTrees), die immer dieselben Strukturen zeigen.
1.
Du fängst an mit einem normalen TreeModel, das alle deine Daten enthält. Wenn du das fertig hast, gehts weiter.
Code:
public class MyModel implements TreeModel {
...
}
2.
Nun bastelst du dir einen Filter.
Code:
public class MyFilter implements TreeModel{
private TreeModel delegate;
public MyFilter(TreeModel delegte) {
this.delegate = delegate;
}
...
}
Den Filter instanziierst du, indem du ihm eine Instanz von MyModel mitgibst.
Im Grunde kannst du zum Rumspielen nun jede Methode von TreeModel im Filter implementieren, indem du jeweils diegleiche Methode des delegates aufrufst.
3.
Danach kannste du Stück für Stück alles Benötigte im Filter umstellen, aber er ist dann schonmal soweit funktional, das man ihn live testen kann.
4.
Richtig lustig wird es, wenn sich Daten ändern. Normalfall: JTree implementiert von Haus aus TreeModelListener und macht ein treeModel.addTreeModelListener(this) für sein Model. Damit das Event-Handling zwischen Model, Filter und Tree funzt, darf man nun die ganzen entsprechenden Methoden implementieren.
4.1
Wir fangen mal damit an, Listener zu registrieren, bzw. Registrierung zu ermöglichen. Dazu bekommen MyModel und MyFilter beide folgenden Code hinzugefügt:
Code:
...
Vector treeModelListeners;
...
/**
* @see javax.swing.tree.TreeModel#addTreeModelListener(javax.swing.event.TreeModelListener)
*/
public void addTreeModelListener(TreeModelListener l) {
// lazy initialization
if (treeModelListeners == null) treeModelListeners = new Vector();
treeModelListeners.addElement(l);
}
/**
* @see javax.swing.tree.TreeModel#removeTreeModelListener(javax.swing.event.TreeModelListener)
*/
public void removeTreeModelListener(TreeModelListener l) {
if (treeModelListeners != null) {
treeModelListeners.removeElement(l);
}
}
Zusätzlich verbinden wir den Filter mit dem Model:
4.2
Weiter gehts mit dem Event-Handling. Model und Filter benachrichtigen ihre Listener mit folgenden Methoden über Änderungen (den Code findet man so im Netz), indem sie bestimmte Methoden im Listener aufrufen (die wir anschließend implementieren):
Code:
...
/**
* Notifies the model listeners of a treeNodesChanged event.
*
* Iterates through the current listener list, and calls the
* treeNodesChanged method for the listener. If the model listener throws an
* an exception or error it will be silently ignored and this method will
* continue to dispatch the event until all listeners have been notified.
*
* @see TreeModelListener#treeNodesChanged(javax.swing.event.TreeModelEvent)
* @param e TreeModelEvent to dispatch.
*/
public void fireTreeNodesChanged(TreeModelEvent e) {
if (treeModelListeners != null) {
Iterator itr = treeModelListeners.iterator();
while (itr.hasNext()) {
try {
TreeModelListener tm = (TreeModelListener) itr.next();
tm.treeNodesChanged(e);
} catch (Throwable t) {
}
}
}
}
/**
* Notifies the model listeners of a treeNodesInserted event.
*
* Iterates through the current listener list, and calls the
* treeNodesInserted method for the listener. If the model listener throws an
* an exception or error it will be silently ignored and this method will
* continue to dispatch the event until all listeners have been notified.
*
* @see TreeModelListener#treeNodesInserted(javax.swing.event.TreeModelEvent)
* @param e TreeModelEvent to dispatch.
*/
public void fireTreeNodesInserted(TreeModelEvent e) {
//log.debug("fireTreeNodesInserted()");
if (treeModelListeners != null) {
Iterator itr = treeModelListeners.iterator();
while (itr.hasNext()) {
try {
TreeModelListener tm = (TreeModelListener) itr.next();
tm.treeNodesInserted(e);
} catch (Throwable t) {
}
}
}
}
/**
* Notifies the model listeners of a treeNodesRemoved event.
*
* Iterates through the current listener list, and calls the
* treeNodesRemoved method for the listener. If the model listener throws an
* an exception or error it will be silently ignored and this method will
* continue to dispatch the event until all listeners have been notified.
*
* @see TreeModelListener#treeNodesRemoved(javax.swing.event.TreeModelEvent)
* @param e TreeModelEvent to dispatch.
*/
public void fireTreeNodesRemoved(TreeModelEvent e) {
if (treeModelListeners != null) {
Iterator itr = treeModelListeners.iterator();
while (itr.hasNext()) {
try {
TreeModelListener tm = (TreeModelListener) itr.next();
tm.treeNodesRemoved(e);
} catch (Throwable t) {
}
}
}
}
/**
* Notifies the model listeners of a treeStructureChanged event.
*
* Iterates through the current listener list, and calls the
* treeStructureChanged method for the listener. If the model listener throws an
* an exception or error it will be silently ignored and this method will
* continue to dispatch the event until all listeners have been notified.
*
* @see TreeModelListener#treeStructureChanged(javax.swing.event.TreeModelEvent)
* @param e TreeModelEvent to dispatch.
*/
public void fireTreeStructureChanged(TreeModelEvent e) {
if (treeModelListeners != null) {
Iterator itr = treeModelListeners.iterator();
while (itr.hasNext()) {
try {
TreeModelListener tm = (TreeModelListener) itr.next();
tm.treeStructureChanged(e);
} catch (Throwable t) {
}
}
}
}
...
4.3
Damit das funzt, fehlen dem Filter als Listener noch die "Empfänger-Methoden" treeNodesChanged(...), treeNodesInserted(...), treeNodesRemoved(...), treeStructureChanged(...). Dafür muss der Filter das Interface javax.swing.event.TreeModelListener implementieren, so wie es ein JTree auch macht (okay, nicht genauso, denn der benutzt eine protected INstanz von TreeModelHandler):.
Deine Aufgabe ist es nun die TreeModelEvents umzubiegen. Löscht du im Model einen Node, benachrichtigt es seine Listener, übergibt ihm eine Referenz auf den gelöschten Node und dessen alte Position (den INdex) den er aus SIcht seines Parents hatte. Ist der benachrichtigte Listener dein Filter, muss der den Event an seine Listener (den JTree) weitergeben. Aus dessen Sicht war der Node aber möglicherweise gar nicht sichtbar (dann kannst du dir die Benachrichtigung sparen) oder aber er lag möglicherweise an einem anderen Index. Diesen musst du umrechnen (wie du es in den TreeModel-Methoden getIndexOfChild(), .. ja auch machen musst), einen neuen Event instanziieren und diesen an die Listener (den JTree) schicken.
Erweiterst du dein Model und denFilter z.B: um eine Methode remove(Object obj), dann lasse den Filter einfach nur die MEthode des delegates (also des Models) aufrufen. Das Model muss sich dann ums Löschen und das Auslösen des Events kümmern. Der Evetn selbst krabbelt dann die ganze Kette nach oben, bis er am JTree ankommt.
Thank you very much!!!
Werd mich am Wochenende gleich erstmal dran setzen, jetzt is n bissi spät... bei mir werden sich aber keine Daten mehr ändern (bis jetzt glaub ich das zumindest nicht) Also brauch ich das mit den ActionListenern doch eigendlich nicht, oder??ß Naja, aber schaden tut's ja auch nicht... wg. Erweiterbarkeit....