# Bitte um ein Beispiel von JXTreeTable



## sindylee2 (19. Aug 2011)

Hallo Zusammen,

Ich möchte eine Tabelle schreiben, drin sollte es jede Menge Komponenten erhalten, wie z.B.:
1.Spalten: ein Baum
2.Spalten: CheckBoxes
3.Spalten: ImageIcron
4.Spalten: URLs
5.Spalten: Texte
...
usw.

Ich habe gegooglet und JXTreeTable gefunden, das kann dies realisieren, aber es gibt leider sehr wenig Beispiele dafür, und ich habe überhaupt keine Idee, wie man das anfangen soll, konnte hier jemand mir helfen, ein Beispiel geben,oder konkrete Tutorial-Links geben?

Danke erst mal!


----------



## Pepe Rohny (19. Aug 2011)

Hi,

hast du schon mal ein Model für einen JTree oder eine JTable selbst entwickelt? Wenn ja hast du eine brauchbare Grundlage. Wenn nein hast du eine interessante Erfahrung vor dir 

Du kannst natürlich auch direkt mit einem JXTreeTableModel beginnen ...

Wie auch immer - wichtig bei der JXTreeTable ist, das Model mit _setTreeTableModel_ hinzuzufügen.

Hier mal eine Skizze des Ansatz: 
	
	
	
	





```
import org.jdesktop.swingx.JXTreeTable;
import org.jdesktop.swingx.treetable.TreeTableModel;

JXTreeTable treeTable = new JXTreeTable();
treeTable.setTreeTableModel(new MyTreeTableModel());

class MyTreeTableModel implements TreeTableModel {
    ...
}
```

Wichtig ist zu verstehen, wann das Model was liefern muss - bzw. was der View erwartet wenn er das Model abfragt.

In diesem Sinne: viel Erfolg!

Pepe


----------



## sindylee2 (19. Aug 2011)

Vielen Dank!
Probiere ich es ab sofort aus:rtfm:


----------



## sindylee2 (31. Aug 2011)

Bis jetzt habe ich doch Fortschritte gekriegt,  und habe ich viel gelernt über JxTreeTable, TreeTableModel(Abstrct,default), TreeTableNode CellRenderer usw.

Nun habe ich wieder mal Frage: JXTreeTable unterstützt also keine Spaltensortierung, wie kann man eine "Customer TableColumnSorter" schreiben, so dass eine JXTreeTable automatisch spaltenweise sortieren kann?

Danke im Voraus!


----------



## Pepe Rohny (31. Aug 2011)

sieh mal hier: Sortable Java Tree Table - Page 2

vielleicht bringt dich das voran

Pepe


----------



## sindylee2 (31. Aug 2011)

hmmm.... danke dir erst mal!

Das hat mir zu mindesten die Richtung von Gedanken korrigiert: es geht also um die "Tree-Sortierung" aber nicht das "Table-Sortierung", oder sagt man mehr Sache auf der "Tree-Seite".


----------



## Pepe Rohny (1. Sep 2011)

da bin ich mir gar nicht mal so sicher.

ich denke, es kommt auf den speziellen Fall an.

man muss nicht unbedingt komplett durch sortieren (wollen).

man kann die Spalte nach den Knoten in der ersten Ebene des Baums (Kinder der Wurzel) sortieren. 

Pepe


----------



## sindylee2 (1. Sep 2011)

Ich habe versucht eine MouseListener anzuhängen, wenn ich auf einen Spaltenkopf klicke, es gibt zwar was Reaktion, aber für Sortierung fehlt es noch viel Sachen.

zum Beispiel:


```
public void addMouseListenerToHeaderInTable(JXTreeTable table) //table ist dann mein JXTreeTable mit DefaultTreeTableModel
	    { 
	        final TableSorter sorter = new TableSorter(table.getModel()); //Meiner Sorter mit Comparator, mit TableModelListener
	        final JTable tableView = table; 
	        tableView.setColumnSelectionAllowed(false); 
	        MouseAdapter listMouseListener = new MouseAdapter() 
	        {
	            @Override
				public void mouseClicked(MouseEvent e) 
	            {
	                TableColumnModel columnModel = tableView.getColumnModel();
	                int viewColumn = columnModel.getColumnIndexAtX(e.getX()); 
	                int column = tableView.convertColumnIndexToModel(viewColumn); 
	                if(e.getClickCount() == 1 && column != -1) 
	                {
	                    System.out.println("Sorting ..." + tableView.getValueAt(1, column)); // Hier wird es die richtige Inhalt ausgegeben
	                    int shiftPressed = e.getModifiers()&InputEvent.SHIFT_MASK; 
	                    boolean ascending = (shiftPressed == 0); 
	                    sorter.sortByColumn(column, ascending);  //Dieser Sorter funktioniert nur bei ein JTable....
	                }
	             }
	         };
	        JTableHeader th = tableView.getTableHeader(); 
	        th.addMouseListener(listMouseListener); 
	    }
```

Ich habe es so verstanden, wenn man Zeilenweise sortieren will, benutzt man das TreeModelListener, kann man Knoten erstmal löschen, speichern in eine Array, Array.sort(); dann wieder in den Baum einfügen; wenn man aber Spaltenweise sortieren will, sollte er das TableModelListener benutzen(aber wie mit den Baum zusammen?)

Oder? Habe ich richtig verstanden?

Wie kann ich weiter machen?


----------



## Pepe Rohny (1. Sep 2011)

> Wie kann ich weiter machen?



na jaaah ... erstmal überlegen was du erreichen - sprich: sortiert haben - willst.

wenn ich das richtig sehe - ich habe das jetzt nur kurz überflogen - kann man einer JXTreeTable nicht  - wie bei einer JTable - einfach einen TableRowSorter hinzufügen.

Pepe


----------



## sindylee2 (2. Sep 2011)

Ich habe wieder bisschen Fortschritt, also habe ich einen TreeTableSorter geschrieben und es funktioniert fast:


```
JXTreeTable treeTable = new JXTreeTable();
		TreeTableSorter sorter = new TreeTableSorter(root,tableheader); 	
		treeTable.setTreeTableModel(sorter);		
		sorter.addMouseListenerToHeaderInTable(treeTable);
```


```
package com.classwizard.cw;

import java.awt.event.InputEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Vector;

import javax.swing.JTable;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;

import org.jdesktop.swingx.JXTreeTable;
import org.jdesktop.swingx.treetable.DefaultTreeTableModel;
import org.jdesktop.swingx.treetable.MutableTreeTableNode;

/**
 * @author SindyLee2 02.09.2011
 *
 */
public class TreeTableSorter extends DynamicTreeTableModel implements TreeModelListener{
	CustomerTreeTableNode             indexes[];
    Vector          sortingColumns = new Vector();
    boolean         ascending = true;
    int 			_column_sorted = -1;
    int             compares;
	CustomerTreeTableNode _root = null;
	CustomerTreeTableNode             oldnodes[];
    public TreeTableSorter(CustomerTreeTableNode root,Vector cols)
    {
    	super(root,cols);
    	_root = root;
        indexes = new CustomerTreeTableNode[0]; // For consistency.  
        oldnodes = new CustomerTreeTableNode[0]; // For consistency. 
        sortingColumns = cols;
    }

    public int getSortedColumn() 
    {
    	return(_column_sorted);
    }
    public boolean getAscending() 
    {
    	return(ascending);
    }

    public int compareRowsByColumn(CustomerTreeTableNode row1, CustomerTreeTableNode row2, int column)
    {
    	Vector rowData1 = row1.getRowData();
    	Vector rowData2 = row2.getRowData();
    	
        Class type = super.getColumnClass(column);
        Object o1 = rowData1.get(column);
        Object o2 = rowData2.get(column); 

        // If both values are null return 0
        if (o1 == null && o2 == null) 
        {
            return 0; 
        }
        else if (o1 == null) // Define null less than everything. 
        { 
            return -1; 
        } 
        else if (o2 == null) 
        { 
            return 1; 
        }

        if (type.getSuperclass() == java.lang.Number.class)
        {
            Number n1 = (Number)rowData1.get(column);
            double d1 = n1.doubleValue();
            Number n2 = (Number)rowData2.get(column);
            double d2 = n2.doubleValue();

            if (d1 < d2)
                return -1;
            else if (d1 > d2)
                return 1;
            else
                return 0;
        }
        else if (type == java.util.Date.class)
        {
            Date d1 = (Date)rowData1.get(column);
            long n1 = d1.getTime();
            Date d2 = (Date)rowData2.get(column);
            long n2 = d2.getTime();

            if (n1 < n2)
                return -1;
            else if (n1 > n2)
                return 1;
            else return 0;
        }
        else if (type == String.class)
        {
            String s1 = (String)rowData1.get(column);
            String s2    = (String)rowData2.get(column);
            int result = s1.compareTo(s2);

            if (result < 0)
                return -1;
            else if (result > 0)
                return 1;
            else return 0;
        }
        else if (type == Boolean.class)
        {
            Boolean bool1 = (Boolean)rowData1.get(column);
            boolean b1 = bool1.booleanValue();
            Boolean bool2 = (Boolean)rowData2.get(column);
            boolean b2 = bool2.booleanValue();

            if (b1 == b2)
                return 0;
            else if (b1) // Define false < true
                return 1;
            else
                return -1;
        }
        else
        {
            Object v1 = rowData1.get(column);
            String s1 = v1.toString();
            Object v2 = rowData2.get(column);
            String s2 = v2.toString();
            int result = s1.compareTo(s2);

            if (result < 0)
                return -1;
            else if (result > 0)
                return 1;
            else return 0;
        }
    }

    public int compare(CustomerTreeTableNode row1, CustomerTreeTableNode row2)
    {
        compares++;
        for(int level = 0; level < sortingColumns.size(); level++)
        {
            Integer column = (Integer)sortingColumns.elementAt(level);
            int result = compareRowsByColumn(row1, row2, column.intValue());
            if (result != 0)
                return ascending ? result : -result;
        }
        return 0;
    }

    public void  reallocateIndexes()
    {
        int rowCount = super.getChildCount(_root);
        indexes = new CustomerTreeTableNode[rowCount];
        for(int row = 0; row < rowCount; row++)
            indexes[row] = (CustomerTreeTableNode) _root.getChildAt(row);
    }

    public void checkModel()
    {
        if (indexes.length !=  super.getChildCount(_root)) 
        {
            reallocateIndexes();
        }
    }

    public void  sort(Object sender)
    {
        checkModel();        
        compares = 0;
//         n2sort();
        // qsort(0, indexes.length-1);
        oldnodes  = (CustomerTreeTableNode[])indexes.clone();
        shuttlesort((CustomerTreeTableNode[])indexes.clone(), indexes, 0, indexes.length);
    }

    public void n2sort() 
    {
        for(int i = 0; i <  super.getChildCount(_root); i++) 
        {
            for(int j = i+1; j <  super.getChildCount(_root); j++) 
            {
                if (compare(indexes[i], indexes[j]) == -1) 
                {
                    swap(i, j);
                }
            }
        }
    }

    public void shuttlesort(CustomerTreeTableNode from[], CustomerTreeTableNode to[], int low, int high) 
    {
        if (high - low < 2) 
        {
            return;
        }
        int middle = (low + high)/2;
        shuttlesort(to, from, low, middle);
        shuttlesort(to, from, middle, high);

        int p = low;
        int q = middle;

        if (high - low >= 4 && compare(from[middle-1], from[middle]) <= 0) 
        {
            for (int i = low; i < high; i++) 
            {
                to[i] = from[i];
            }
            return;
        }

        // A normal merge. 

        for(int i = low; i < high; i++) 
        {
            if (q >= high || (p < middle && compare(from[p], from[q]) <= 0)) 
            {
                to[i] = from[p++];
            }
            else 
            {
                to[i] = from[q++];
            }
        }
    }

    public void swap(int i, int j) 
    {
    	CustomerTreeTableNode tmp = indexes[i];
        indexes[i] = indexes[j];
        indexes[j] = tmp;
    }

    public void sortByColumn(int column, boolean ascending) 
    {    	
        this.ascending = ascending;
        sortingColumns.removeAllElements();
        sortingColumns.addElement(new Integer(column));
        sort(this);
        //  nodes must be new arranged to update the tree   
        DefaultTreeTableModel oldmodel = new DefaultTreeTableModel(_root);
        for(int k=0; k<oldnodes.length;k++){
        	CustomerTreeTableNode oldn = oldnodes[k];
        	 oldmodel.removeNodeFromParent(oldn);
        }
        DefaultTreeTableModel newmodel = new DefaultTreeTableModel(_root);
        for(int i = 0; i<indexes.length;i++){
            CustomerTreeTableNode sr = indexes[i];
//            Vector srRowData = sr.getRowData();
//            System.out.println("sorted result node: " + srRowData);
            newmodel.insertNodeInto(sr, _root, i);           
        }
//        System.out.println(_root.getChildCount());  
        for(int j = 0; j<indexes.length;j++){
//            System.out.println(((CustomerTreeTableNode) _root.getChildAt(j)).getRowData());  //The Order is here already correct!
        fireTreeStructureChanged(this, getPathToRoot((CustomerTreeTableNode) _root.getChildAt(j)), null, null); //??????? but here is lost again.....  
//Die schon richtig sortierte Spalteninhalte sind wieder ducheinander!?
        }
    }

	public void treeNodesChanged(TreeModelEvent e) {
		int[] indices = e.getChildIndices();
		TreePath path = e.getTreePath();
		sort(e.getTreePath());
		fireTreeNodesChanged(this, path.getPath(),indices,e.getChildren());

	}

	public void treeNodesInserted(TreeModelEvent e) {
		int[] indices = e.getChildIndices();
		TreePath path = e.getTreePath();
		sort(e.getTreePath());
		fireTreeNodesInserted(this, path.getPath(),indices,e.getChildren());
		
	}

	public void treeNodesRemoved(TreeModelEvent e) {
		int[] indices = e.getChildIndices();
		TreePath path = e.getTreePath();
		sort(e.getTreePath());
		fireTreeNodesRemoved(this, path.getPath(),indices,e.getChildren());
		
	}

	public void treeStructureChanged(TreeModelEvent e) {
		 reallocateIndexes();
		fireTreeStructureChanged(e.getTreePath(), null, null, null);
		
	}
	
	public void addMouseListenerToHeaderInTable(JXTreeTable table) 
    { 
        final TreeTableSorter sorter = this; 
        final JTable tableView = table; 
        tableView.setColumnSelectionAllowed(false); 
        MouseAdapter listMouseListener = new MouseAdapter() 
        {
            @Override
			public void mouseClicked(MouseEvent e) 
            {
                TableColumnModel columnModel = tableView.getColumnModel();
                int viewColumn = columnModel.getColumnIndexAtX(e.getX()); 
                int column = tableView.convertColumnIndexToModel(viewColumn); 
                if(e.getClickCount() == 1 && column != -1) 
                {	                	
//                    System.out.println("Sorting ..." + tableView.getValueAt(1, column)); 
                    int shiftPressed = e.getModifiers()&InputEvent.SHIFT_MASK; 
                    boolean ascending = (shiftPressed == 0);
                   	sorter.sortByColumn(column, ascending);               
                }
             }
         };
        JTableHeader th = tableView.getTableHeader(); 
        th.addMouseListener(listMouseListener); 
    }

}
```

Das Problem ist nun: warum funktioniert das "fireTreeStructureChanged(...)" nicht?  (Zeile 269)


----------



## Pepe Rohny (2. Sep 2011)

> Das Problem ist nun: warum funktioniert das "fireTreeStructureChanged(...)" nicht? (Zeile 269)


gute Frage :bahnhof:

kannst du mal den wesentlichen code (JXTreeTable mit Sorter in JFrame, bei den Sortier-Methoden reichen die Köpfe) in ein kleines lauffähiges Programm packen? Denn seh' ich mal 'drüber

Pepe

P.S.
inzwischen 'hab ich mal meinen Ansatz implementiert: 
	
	
	
	





```
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Vector;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.WindowConstants;
import javax.swing.event.TreeModelListener;
import javax.swing.table.JTableHeader;
import javax.swing.tree.TreePath;

import org.jdesktop.swingx.JXTreeTable;
import org.jdesktop.swingx.treetable.TreeTableModel;

final class SortableJXTreeTableSample 
extends JFrame 
implements MouseListener, Runnable {

    private static final long serialVersionUID = 1L;

    private final JTableHeader treeTableHeader;
    private final SortableTreeTableModel sortableTreeTableModel;

    private SortableJXTreeTableSample() {

        super("SortableJXTreeTableSample");

        setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);

        JXTreeTable treeTable = new JXTreeTable();
        treeTableHeader = treeTable.getTableHeader();
        treeTableHeader.addMouseListener(this);

        Vector<TreeNode> treeModelContent = new Vector<TreeNode>();
        TreeNode treeNode = new TreeNode("Swing user");
        treeNode.addChild("sindylee2");
        treeNode.addChild("Pepe Rohny");
        treeModelContent.add(treeNode);
        treeNode = new TreeNode("SwingX user");
        treeNode.addChild("sindylee2");
        treeNode.addChild("Pepe Rohny");
        treeModelContent.add(treeNode);

        sortableTreeTableModel = new SortableTreeTableModel(treeModelContent);
        treeTable.setTreeTableModel(sortableTreeTableModel);

        JPanel panel = new JPanel(new BorderLayout());
        panel.add(new JScrollPane(treeTable), BorderLayout.CENTER);

        panel.setPreferredSize(new Dimension(320, 180));

        setContentPane(panel);

        pack();

    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new SortableJXTreeTableSample());
    }

    @Override
    public void mouseClicked(MouseEvent evt) {
        sortableTreeTableModel.sortColumn(treeTableHeader.getColumnModel().getColumnIndexAtX(evt.getX()));
    }

    @Override
    @SuppressWarnings("unused")
    public void mouseEntered(MouseEvent evt) {
    }

    @Override
    @SuppressWarnings("unused")
    public void mouseExited(MouseEvent evt) {
    }

    @Override
    @SuppressWarnings("unused")
    public void mousePressed(MouseEvent evt) {
    }

    @Override
    @SuppressWarnings("unused")
    public void mouseReleased(MouseEvent evt) {
    }

    @Override
    public void run() {
        setVisible(true);
    }

    private class SortableTreeTableModel 
    implements TreeTableModel {

        private final Vector<TreeNode> root;
        private final Vector<TreeModelListener> treeModelListenerList;

        SortableTreeTableModel(Vector<TreeNode> root) {
            this.root = root;
            treeModelListenerList = new Vector<TreeModelListener>();
        }

        @Override
        public void addTreeModelListener(TreeModelListener treeModelListener) {
            treeModelListenerList.add(treeModelListener);
        }

        @Override
        public Object getChild(Object parent, int index) {
            Object child = null;
            if (parent == root) {
                child = root.elementAt(index);
            } else {
                child = ((TreeNode)parent).children.elementAt(index);
            }
            return child;
        }

        @Override
        public int getChildCount(Object parent) {
            int childCount = 0;
            if (parent == root) {
                childCount = root.size();
            } else {
                childCount = ((TreeNode)parent).children.size();
            }
            return childCount;
        }

        @Override
        public Class<?> getColumnClass(int columnIndex) {
            return null;
        }

        @Override
        public int getColumnCount() {
            return 2;
        }

        @Override
        public String getColumnName(int column) {
            return column == 0 ? "Name" : "# of children";
        }

        @Override
        public int getHierarchicalColumn() {
            return 0;
        }

        @Override
        public int getIndexOfChild(Object parent, Object child) {
            return 0;
        }

        @Override
        public Object getRoot() {
            return root;
        }

        @Override
        public Object getValueAt(Object node, int column) {
            Object value = null;
            if (column == 0) {
                value = node.toString();
            } else {
                value = "" + (node instanceof TreeNode ? ((TreeNode)node).children.size() : 0);
            }
            return value;
        }

        @Override
        public boolean isCellEditable(Object node, int column) {
            return false;
        }

        @Override
        public boolean isLeaf(Object node) {
            return node instanceof TreeNodeChild;
        }

        @Override
        public void removeTreeModelListener(TreeModelListener treeModelListener) {
            treeModelListenerList.remove(treeModelListener);
        }

        public void sortColumn(int columnIndex) {
        }

        @Override
        public void valueForPathChanged(TreePath path, Object newValue) {
        }

        @Override
        public void setValueAt(Object value, Object node, int column) {
        }

    }

    private class TreeNode {

        final Vector<TreeNodeChild> children;
        final String name;

        TreeNode(String name) {
            children = new Vector<TreeNodeChild>();
            this.name = name;
        }

        public void addChild(String childName) {
            children.add(new TreeNodeChild(childName));
        }

        @Override
        public String toString() {
            return name;
        }

    }

    private class TreeNodeChild {

        final String name;

        TreeNodeChild(String name) {
            this.name = name;
        }

        @Override
        public String toString() {
            return name;
        }

    }

}
```

das Problem der Sortierung liegt jetzt in der Logik in _public Object getChild(Object parent, int index)_ und muss eben für richtige/echte Daten angepasst werden

Pepe


----------



## sindylee2 (7. Sep 2011)

Ich baue gerade ein Projekt auf, das leider sehr kompliziert ist, es ist schwere den Kode zu einem kleinen lauffähigen Programm umzuändern. Aber zum Glück habe ich endlich das Problem behoben.

mein TreeTableSorter sieht also so aus:


```
import java.awt.event.InputEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.Vector;

import javax.swing.JTable;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;

import org.jdesktop.swingx.JXTreeTable;
import org.jdesktop.swingx.treetable.DefaultTreeTableModel;
import org.jdesktop.swingx.treetable.MutableTreeTableNode;
import org.jdesktop.swingx.treetable.TreeTableModel;
import org.jdesktop.swingx.treetable.TreeTableNode;

public class TreeTableSorter extends DynamicTreeTableModel implements TreeModelListener{
	CustomerTreeTableNode             indexes[];
    Vector          sortingColumns = new Vector();
    boolean         ascending = true;
    int 			_column_sorted = -1;
    int             compares;
	CustomerTreeTableNode _root = null;
	CustomerTreeTableNode             oldnodes[];
    Vector oldttn = null;
    Vector indxs = null; 
    Vector _cols = new Vector();
    public TreeTableModel model = null;
    
    /**constructor*/
    public TreeTableSorter(CustomerTreeTableNode root,Vector cols, TreeTableModel cttm)
    {
    	super(root,cols);
    	_root = root;
    	for(int i=0; i<cols.size();i++) _cols.add(cols.get(i));
        indexes = new CustomerTreeTableNode[0]; // For consistency.  
        oldnodes = new CustomerTreeTableNode[0]; // For consistency. 
        sortingColumns = cols;
        oldttn = new Vector();        
        model = cttm;
    }
    public int getSortedColumn() 
    {
    	return(_column_sorted);
    }
    public boolean getAscending() 
    {
    	return(ascending);
    }

    public int compareRowsByColumn(CustomerTreeTableNode row1, CustomerTreeTableNode row2, int column)
    {
    	Vector rowData1 = row1.getRowData();
    	Vector rowData2 = row2.getRowData();
    	
        Class type = super.getColumnClass(column);
        Object o1 = rowData1.get(column);
        Object o2 = rowData2.get(column); 

        // If both values are null return 0
        if (o1 == null && o2 == null) 
        {
            return 0; 
        }
        else if (o1 == null) // Define null less than everything. 
        { 
            return -1; 
        } 
        else if (o2 == null) 
        { 
            return 1; 
        }

        if (type.getSuperclass() == java.lang.Number.class)
        {
            Number n1 = (Number)rowData1.get(column);
            double d1 = n1.doubleValue();
            Number n2 = (Number)rowData2.get(column);
            double d2 = n2.doubleValue();

            if (d1 < d2)
                return -1;
            else if (d1 > d2)
                return 1;
            else
                return 0;
        }
        else if (type == java.util.Date.class)
        {
            Date d1 = (Date)rowData1.get(column);
            long n1 = d1.getTime();
            Date d2 = (Date)rowData2.get(column);
            long n2 = d2.getTime();

            if (n1 < n2)
                return -1;
            else if (n1 > n2)
                return 1;
            else return 0;
        }
        else if (type == String.class)
        {
            String s1 = (String)rowData1.get(column);
            String s2    = (String)rowData2.get(column);
            int result = s1.compareTo(s2);

            if (result < 0)
                return -1;
            else if (result > 0)
                return 1;
            else return 0;
        }
        else if (type == Boolean.class)
        {
            Boolean bool1 = (Boolean)rowData1.get(column);
            boolean b1 = bool1.booleanValue();
            Boolean bool2 = (Boolean)rowData2.get(column);
            boolean b2 = bool2.booleanValue();

            if (b1 == b2)
                return 0;
            else if (b1) // Define false < true
                return 1;
            else
                return -1;
        }
        else
        {
            Object v1 = rowData1.get(column);
            String s1 = v1.toString();
            Object v2 = rowData2.get(column);
            String s2 = v2.toString();
            int result = s1.compareTo(s2);

            if (result < 0)
                return -1;
            else if (result > 0)
                return 1;
            else return 0;
        }
    }

    public int compare(CustomerTreeTableNode row1, CustomerTreeTableNode row2)
    {
        compares++;
        for(int level = 0; level < sortingColumns.size(); level++)
        {
            Integer column = (Integer)sortingColumns.elementAt(level);
            int result = compareRowsByColumn(row1, row2, column.intValue());
            if (result != 0)
                return ascending ? result : -result;
        }
        return 0;
    }

    public void  reallocateIndexes()
    {
        int rowCount = super.getChildCount(_root);
        indexes = new CustomerTreeTableNode[rowCount];
        for(int row = 0; row < rowCount; row++)
            indexes[row] = (CustomerTreeTableNode) _root.getChildAt(row);
    }

    public void checkModel()
    {
        if (indexes.length !=  super.getChildCount(_root)) 
        {
            reallocateIndexes();
        }
    }

    public void  sort(Object sender)
    {
        checkModel();        
        compares = 0;
//         n2sort();
        // qsort(0, indexes.length-1);
        oldnodes  = (CustomerTreeTableNode[])indexes.clone();
        shuttlesort((CustomerTreeTableNode[])indexes.clone(), indexes, 0, indexes.length);
    }

    public void n2sort() 
    {
        for(int i = 0; i <  super.getChildCount(_root); i++) 
        {
            for(int j = i+1; j <  super.getChildCount(_root); j++) 
            {
                if (compare(indexes[i], indexes[j]) == -1) 
                {
                    swap(i, j);
                }
            }
        }
    }

    public void shuttlesort(CustomerTreeTableNode from[], CustomerTreeTableNode to[], int low, int high) 
    {
        if (high - low < 2) 
        {
            return;
        }
        int middle = (low + high)/2;
        shuttlesort(to, from, low, middle);
        shuttlesort(to, from, middle, high);

        int p = low;
        int q = middle;

        if (high - low >= 4 && compare(from[middle-1], from[middle]) <= 0) 
        {
            for (int i = low; i < high; i++) 
            {
                to[i] = from[i];
            }
            return;
        }

        // A normal merge. 

        for(int i = low; i < high; i++) 
        {
            if (q >= high || (p < middle && compare(from[p], from[q]) <= 0)) 
            {
                to[i] = from[p++];
            }
            else 
            {
                to[i] = from[q++];
            }
        }
    }

    public void swap(int i, int j) 
    {
    	CustomerTreeTableNode tmp = indexes[i];
        indexes[i] = indexes[j];
        indexes[j] = tmp;
    }

    public void sortByColumn(int column, boolean ascending) 
    {    	
        this.ascending = ascending;
        sortingColumns.removeAllElements();
        sortingColumns.addElement(new Integer(column));
        sort(this);
        
        // old index must be saved   
        //  nodes must be new arranged to update the tree
        indxs = new Vector();
        for(int l=0; l<_root.getChildCount();l++){
            oldttn.add(getPathToRoot((CustomerTreeTableNode) _root.getChildAt(l)));
            indxs.add(l);
        }
        for(int k=0; k<oldnodes.length;k++){
        	CustomerTreeTableNode oldn = oldnodes[k];            
        	_root.remove(oldn);
        }
        for(int i = 0; i<indexes.length;i++){
            CustomerTreeTableNode sr = indexes[i];
            _root.insert(sr, i);
        }  
//fireTreeStructureChanged() funktioniert gar nicht gut. Hier braucht man einfach das Model neu zu setzen.
//        setModel(model);
//        System.out.println("**************");
//        for(int t=0; t<_root.getChildCount();t++){   //(TreeTableNode[])oldttn.get(t)
//            	fireTreeStructureChanged(this,getPathToRoot((CustomerTreeTableNode) _root.getChildAt(t)), null,null);
//        }
    	
    }    
	public void treeNodesChanged(TreeModelEvent e) {
		int[] indices = e.getChildIndices();
		TreePath path = e.getTreePath();
		sort(e.getTreePath());
		fireTreeNodesChanged(this, path.getPath(),indices,e.getChildren());

	}

	public void treeNodesInserted(TreeModelEvent e) {
		int[] indices = e.getChildIndices();
		TreePath path = e.getTreePath();
		sort(e.getTreePath());
		fireTreeNodesInserted(this, path.getPath(),indices,e.getChildren());
		
	}

	public void treeNodesRemoved(TreeModelEvent e) {
		int[] indices = e.getChildIndices();
		TreePath path = e.getTreePath();
		sort(e.getTreePath());
		fireTreeNodesRemoved(this, path.getPath(),indices,e.getChildren());
		
	}

	public void treeStructureChanged(TreeModelEvent e) {
		 reallocateIndexes();
//		fireTreeStructureChanged(e);
		
	}
	
	public void addMouseListenerToHeaderInTable(JXTreeTable table) 
    { 
        final TreeTableSorter sorter = this; 
        final JXTreeTable tableView = table; 
        tableView.setColumnSelectionAllowed(false); 
        MouseAdapter listMouseListener = new MouseAdapter() 
        {
            @Override
			public void mouseClicked(MouseEvent e) 
            {
                TableColumnModel columnModel = tableView.getColumnModel();
                int viewColumn = columnModel.getColumnIndexAtX(e.getX()); 
                int column = tableView.convertColumnIndexToModel(viewColumn); 
                if(e.getClickCount() == 1 && column != -1) 
                {	                	
                    int shiftPressed = e.getModifiers()&InputEvent.SHIFT_MASK; 
                    boolean ascending = (shiftPressed == 0);
                   	sorter.sortByColumn(column, ascending);  
                   	tableView.setTreeTableModel(new DynamicTreeTableModel(_root,_cols));  //hier ist ganz wichtig, um das Model neu zu setzen.(update Model)
                }
             }
         };
        JTableHeader th = tableView.getTableHeader(); 
        th.addMouseListener(listMouseListener); 
    }

}
```

Fazit: Der Prinzip von JXTreeTable ist seht ähnlich von JTree und JTable, oder sagt man das ist eine Zusammenfassung von JTree und JTable. Nur muss man genau wissen, wann, wo und mit welchem Model sollte man benutzen.


----------



## Pepe Rohny (7. Sep 2011)

> Nur muss man genau wissen, wann, wo und mit welchem Model sollte man benutzen.


 :toll:

Pepe


----------

