Hallo, da Swing ja leider keine Möglichkeit einer TreeTable anbietet, benutze ich diese Implementierung in meinem Programm: http://www.hameister.org/JavaSwingTreeTable.html.
Das Problem ist, dass ich JCheckboxen in dieser Gui-Komponente habe, die ich auch ändern können will. Dabei sollen außerdem, wenn die Root Checkbox aktiviert wurde, alle anderen Checkboxen ebenfalls aktiviert werden. Wird eine “subroot” checkbox angewählt wiederum deren Kinder Checkboxen. Der Code dazu funktioniert auch, leider werden diese Ändeurngen immer erst angezeigt wenn ich die TreeTable falte und wieder aufklappe, sprich neuzeichnen. Über myTreeTable.updateUI(); könnte ich das auch neu zeichnen, aber ich setze ja die Änderungen im Model. Das heißt eigentlich müsste ich hier im Model eine der fire…() Methoden aufrufen.
Hier mal der Code mit der ich den Wert der Checkboxen ändere:
private void setValueForCheckbox(Object node, Object aValue,
Method method) throws IllegalArgumentException,
IllegalAccessException, InvocationTargetException {
//Root
if (node == root) {
//alle sub-roots
for (int i = 0; i < getChildCount(root); i++) {
TVDataNode everySubRoot = (TVDataNode) getChild(root, i);
method.invoke(everySubRoot, (Boolean) aValue);
//children von sub-roots
for (int j = 0; j < everySubRoot.getChildren().size(); j++) {
method.invoke(((TVDataNode) getChild(everySubRoot, j)),
(Boolean) aValue);
}
}
}
// 1 subroot & children
if(isChild(root,node)) {
for(int i = 0;i<getChildCount(node);i++) {
method.invoke((TVDataNode)getChild(node,i), (Boolean)aValue);
}
}
}
public void setValueAt(Object aValue, Object node, int column)
throws IllegalArgumentException, SecurityException,
IllegalAccessException, InvocationTargetException,
NoSuchMethodException {
switch (column) {
case 0:
((TVDataNode) node).setRootName((String) aValue);
break;
case 1:
((TVDataNode) node).setName((String) aValue);
break;
case 2:
((TVDataNode) node).setSeen((Boolean) aValue);
setValueForCheckbox(node, aValue,
TVDataNode.class.getDeclaredMethod("setSeen", Boolean.TYPE));
break;
case 3:
((TVDataNode) node).setBought((Boolean) aValue);
setValueForCheckbox(node, aValue,
TVDataNode.class.getDeclaredMethod("setBought",
Boolean.TYPE));
break;
default:
break;
}
}
Mein AbstractTreeTableModel von dem das Model in dem diese Methoden sich befinden erbt, findet ihr nochmal hier: (oder auf der oben verlinkten Seite):
public abstract class MyAbstractTreeTableModel implements MyTreeTableModel {
protected Object root;
protected EventListenerList listenerList = new EventListenerList();
private static final int CHANGED = 0;
private static final int INSERTED = 1;
private static final int REMOVED = 2;
private static final int STRUCTURE_CHANGED = 3;
public MyAbstractTreeTableModel(Object root) {
this.root = root;
}
public Object getRoot() {
return root;
}
public void setRoot(Object root) {
this.root = root;
}
public boolean isLeaf(Object node) {
return getChildCount(node) == 0;
}
public void valueForPathChanged(TreePath path, Object newValue) {
}
/**
* Die Methode wird normalerweise nicht aufgerufen.
*/
public int getIndexOfChild(Object parent, Object child) {
return 0;
}
public void addTreeModelListener(TreeModelListener l) {
listenerList.add(TreeModelListener.class, l);
}
public void removeTreeModelListener(TreeModelListener l) {
listenerList.remove(TreeModelListener.class, l);
}
private void fireTreeNode(int changeType, Object source, Object[] path, int[] childIndices, Object[] children) {
Object[] listeners = listenerList.getListenerList();
TreeModelEvent e = new TreeModelEvent(source, path, childIndices, children);
for (int i = listeners.length - 2; i >= 0; i -= 2) {
if (listeners** == TreeModelListener.class) {
switch (changeType) {
case CHANGED:
((TreeModelListener) listeners[i + 1]).treeNodesChanged(e);
break;
case INSERTED:
((TreeModelListener) listeners[i + 1]).treeNodesInserted(e);
break;
case REMOVED:
((TreeModelListener) listeners[i + 1]).treeNodesRemoved(e);
break;
case STRUCTURE_CHANGED:
((TreeModelListener) listeners[i + 1]).treeStructureChanged(e);
break;
default:
break;
}
}
}
}
protected void fireTreeNodesChanged(Object source, Object[] path, int[] childIndices, Object[] children) {
fireTreeNode(CHANGED, source, path, childIndices, children);
}
protected void fireTreeNodesInserted(Object source, Object[] path, int[] childIndices, Object[] children) {
fireTreeNode(INSERTED, source, path, childIndices, children);
}
protected void fireTreeNodesRemoved(Object source, Object[] path, int[] childIndices, Object[] children) {
fireTreeNode(REMOVED, source, path, childIndices, children);
}
protected void fireTreeStructureChanged(Object source, Object[] path, int[] childIndices, Object[] children) {
fireTreeNode(STRUCTURE_CHANGED, source, path, childIndices, children);
}
}
Ich bin mir fast sicher, dass es am besten wäre wenn ich fireTreeNodesChanged() aufrufen würde aus meiner setValueForCheckbox Methode, aber ich bin mir nicht sicher welche Argumente ich übergeben muss.
Viele Grüße