# JTreeTable - Problem Mausaktionen von Tabelle an Tree weiterzuleiten



## shutdown (25. Oktober 2007)

Hi!

Ich hätte da mal ein Problem, zu dem ich im Netz nicht so richtig was finde.
Es gibt ja verschiedene Tutorials zum dem Thema TreeTables in Java (aus JTree und JTable).
- Seltsamerweise funktioniert bei mir kein einziges der Code-Beispiele, aber ok.

Jedenfalls habe ich das jetzt mal bei mir nachvollzogen und nach diesen Beispielen einen TreeTable gebaut.

Allerdings habe ich jetzt das Problem, dass keine Mausaktionen, die ich vornehme, an den JTree weitergeleitet werden - mit anderen Worten, will ich den Tree expandieren oder kollabieren lassen, dann passiert nichts.

Nach meinem bisherigen Verständnis ist ein Renderer in Swing tatsächlich auch nur zum Darstellen dar und gibt daher auch gar keine Events an innere Komponenten weiter - zumindest dachte ich das bisher, lt. den Tutorials muss man ja keinen Cell-Editor schreiben um den Tree tatsächlich direkt anzusprechen.

Jedenfalls habe ich nun genau das Verhalten, dass der Tree nicht angesprochen wird.
Wenn sich jemand schon mal damit beschäftigt hat, wäre ich für jede Hilfe dankbar.

cu shutdown

Hier mein Code:

```
import java.awt.Component;
import java.awt.Graphics;

import javax.swing.DefaultCellEditor;
import javax.swing.DefaultListSelectionModel;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTree;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeSelectionModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreeSelectionModel;

public class JTreeTable extends JTable {
	private TreeTableRenderer tree;
	private TreeTableModel model;

	public JTreeTable() {
		DefaultMutableTreeNode root = new DefaultMutableTreeNode("root");
		root.add(new DefaultMutableTreeNode("sub"));
		root.add(new DefaultMutableTreeNode("subbie2"));
		DefaultMutableTreeNode subbie3 = new DefaultMutableTreeNode("subbi3");
		root.add(subbie3);
		subbie3.add(new DefaultMutableTreeNode("hallo"));
		tree = new TreeTableRenderer(root);
		model = new TreeTableModel(tree);
		setModel(model);

		setDefaultRenderer(TreeTableRenderer.class, tree);
		setShowGrid(false);
				
		tree.expandRow(tree.getRowCount()-1);
	}

	
	
	
	@Override
	public void updateUI() {
		super.updateUI();

		if(tree != null)
			tree.updateUI();
	}


	

	public JTreeTable(Object[][] rowData, Object[] columnNames) {
		super(rowData, columnNames);
		// TODO Auto-generated constructor stub
	}

	public int getEditingRow() {
		if (getColumnClass(editingColumn) == TreeTableRenderer.class)
			return -1;
		
		return editingRow;
	}

	class TreeTableRenderer extends JTree implements TableCellRenderer {

		private int visibleRow;

		public TreeTableRenderer(TreeNode root) {
			super(root);
			setSelectionModel(new DefaultTreeSelectionModel());
		}

		@Override
		public void paint(Graphics g) {
			g.translate(0, -visibleRow * getRowHeight());
			super.paint(g);
		}

		@Override
		public void setBounds(int x, int y, int width, int height) {
			super.setBounds(x, 0, width, JTreeTable.this.getHeight());
		}

		@Override
		public Component getTableCellRendererComponent(JTable table,
				Object value, boolean isSelected, boolean hasFocus, int row,
				int column) {

			visibleRow = row;
			return this;
		}

	}

	class TreeTableModel extends DefaultTableModel {
		private JTree tree;

		private String[] headers = new String[] { "node", "id", "sonstwas" };

		public TreeTableModel(JTree tree) {
			this.tree = tree;
		}

		@Override
		public int getRowCount() {
			if (tree == null)
				return 0;

			return tree.getRowCount();
		}

		@Override
		public Object getValueAt(int row, int column) {
			if (column == 0)
				return tree;
			else
				return "1";
		}

		@Override
		public boolean isCellEditable(int row, int column) {
			return true;
		}

		@Override
		public Class<?> getColumnClass(int columnIndex) {
			if (columnIndex == 0)
				return tree.getClass();

			return getValueAt(0, columnIndex).getClass();
		}

		@Override
		public int getColumnCount() {
			return headers.length;
		}

		@Override
		public String getColumnName(int column) {
			return headers[column];
		}

	}
	
	
	public static void main(String[] args) {
		try {
			UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
		} catch (Exception e) {	e.printStackTrace(); }
		
		JFrame f = new JFrame();
		f.setSize(300, 400);

		f.add(new JTreeTable(
		// new Object[][] {
				// {"asd", "safd"},
				// {"sadjfl", "lsadjfasdf"}
				// }, new String[] {"nr", "sonstwas"}
				));

		f.setVisible(true);
		f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}
}
```


----------



## shutdown (26. Oktober 2007)

Vielleicht hab ich's auch etwas zu kompliziert erklärt, darum ein neuer Versuch:

Der Jtree wird mir in der ersten Spalte meiner Tabelle korrekt angezeigt.
Allerdings auch nicht mehr - eben nur angezeigt.
Er ist in keinster Weise interaktiv.
Ein Selection-Listener auf diesem Baum wird beim Anklicken der Zelle nicht ausgelöst.

Ich habe jetzt mal versucht, die Selection-Events von der Zelle an den Tree weiterzuleiten - das würde prinzipiell funktionieren, allerdings kann er die Komponente dann nicht richtig darstellen. Es ist auch eine Krücke, die in keinem Tutorial so beschrieben wurde, weshalb ich davon ausgehe, dass sie eigentlich gar nicht nötig ist.

Für Hilfe bin ich weiter sehr dankbar
shutdown


----------



## shutdown (26. Oktober 2007)

Okay, ich habs jetzt vorerst mal hinbekommen.
Es ist zusätzlich noch notwendig den Renderer auch als Editor zu implementieren und diesen mit einem bestimmten Verhalten auszustatten. 

Da davon aber in keinem  Tutorial was stand, gehe ich nicht davon aus, dass das die beste Lösung ist.

cu shutdown


```
import java.awt.Component;
import java.awt.Graphics;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.ContainerEvent;
import java.awt.event.ContainerListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.EventObject;
import java.util.Vector;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTree;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeSelectionModel;
import javax.swing.tree.TreeNode;

public class JTreeTable extends JTable {

	private TreeTableRenderer tree;
	private TreeTableModel model;

	public JTreeTable() {
		super();
		// TODO Auto-generated constructor stub
		DefaultMutableTreeNode root = new DefaultMutableTreeNode("root");
		root.add(new DefaultMutableTreeNode("adsfjlsd"));
		DefaultMutableTreeNode sub = new DefaultMutableTreeNode("adsfj23234lsd");
		sub.add(new DefaultMutableTreeNode("asdlf1111111"));
		DefaultMutableTreeNode sub2 = new DefaultMutableTreeNode("adsfj23234lsasdfasdfasdfd");
		sub.add(sub2);
		sub2.add(new DefaultMutableTreeNode("asdjflasöd1119999"));
		root.add(sub);		
		root.add(new DefaultMutableTreeNode("adsfj23234lsasdfasdfasdfd"));
		tree = new TreeTableRenderer(root);
		model = new TreeTableModel(tree);
		setModel(model);
		setDefaultRenderer(TreeTableRenderer.class, tree);
		setDefaultEditor(TreeTableRenderer.class,tree);
						
		setShowGrid(false);
	}

	public JTreeTable(int numRows, int numColumns) {
		super(numRows, numColumns);

	}

	public JTreeTable(Object[][] rowData, Object[] columnNames) {
		super(rowData, columnNames);

	}

	public JTreeTable(TableModel dm, TableColumnModel cm, ListSelectionModel sm) {
		super(dm, cm, sm);
		// TODO Auto-generated constructor stub
	}

	public JTreeTable(TableModel dm, TableColumnModel cm) {
		super(dm, cm);
		// TODO Auto-generated constructor stub
	}

	public JTreeTable(TableModel dm) {
		super(dm);
		// TODO Auto-generated constructor stub
	}

	public JTreeTable(Vector rowData, Vector columnNames) {
		super(rowData, columnNames);
		// TODO Auto-generated constructor stub
	}
	
	

	
	

	public int getEditingRow() {
		if(getColumnClass(editingColumn) == TreeTableRenderer.class)
			return -1;
		
		return super.getEditingRow();
	}






	class TreeTableRenderer extends JTree implements TableCellRenderer, TableCellEditor {

		protected int visibleRow;

		public TreeTableRenderer(TreeNode root) {
			super(root);
			setSelectionModel(new DefaultTreeSelectionModel() {
				public void DefaultTreeSelectionModel() {
					JTreeTable.this.setSelectionModel(listSelectionModel);
				}
			});

		}

		public void setBounds(int x, int y, int width, int height) {
			// TODO Auto-generated method stub
			super.setBounds(x, 0, width, JTreeTable.this.getHeight());
		}

		public void paint(Graphics g) {
			System.out.println(visibleRow);
			g.translate(0, -visibleRow * getRowBounds(visibleRow).height);
			super.paint(g);
		}

		public Component getTableCellRendererComponent(JTable table,
				Object value, boolean isSelected, boolean hasFocus, int row,
				int column) {
			// TODO Auto-generated method stub

			if(isSelected) {
				setBackground( table.getSelectionBackground() );
			} else {
				setBackground( table.getBackground() );
			}
		        
		
			visibleRow = row;
			return this;
		}
		
		 

		public Component getTableCellEditorComponent(JTable table,
				Object value, boolean isSelected, int row, int column) {
			
			return tree;
		}

		public void addCellEditorListener(CellEditorListener l) {
		}

		public void cancelCellEditing() {
		}

		public Object getCellEditorValue() {
			return null;
		}

		public boolean isCellEditable(EventObject anEvent) {
			return true;
		}

		public void removeCellEditorListener(CellEditorListener l) {
		}

		public boolean shouldSelectCell(EventObject anEvent) {
			return true;
		}

		public boolean stopCellEditing() {
			SwingUtilities.invokeLater(new Runnable() {
				public void run() {
					tree.updateUI();
					JTreeTable.this.updateUI();
				}
			});
			return true;
		}
		
		 
		 
		
	}

	class TreeTableModel extends DefaultTableModel {

		private JTree tree;

		private String[] headers = new String[] { "node", "nr", "name" };

		public TreeTableModel(JTree tree) {
			this.tree = tree;
			this.setColumnIdentifiers(headers);			
		}

		public int getColumnCount() {
			return headers.length;
		}

		public int getRowCount() {
			if (tree == null)
				return 0;
			return tree.getRowCount();
		}

		public Object getValueAt(int row, int column) {
			if (column == 0)
				return tree;
			else
				return "1";
		}

		public Class getColumnClass(int c) {
			return getValueAt(0, c).getClass();
		}

		public String getColumnName(int column) {
			return headers[column];
		}

		
		public boolean isCellEditable(int row, int col) {
		      if( col == 0 )
		         return true;

		       return false;
		}
	}
		
	public static void main(String[] args) {
		
		try {
			UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
		} catch (Exception e) {	e.printStackTrace();}
		
		JFrame f = new JFrame();
		f.setSize(500, 500);

		JScrollPane pane = new JScrollPane();
		// JTable table = new JTreeTable(new Object[][] { { "1", "hallo" },
		// { "2", "gullo" } }, new String[] { "nr", "name" });

		JTreeTable table = new JTreeTable();
		DefaultMutableTreeNode root = new DefaultMutableTreeNode("root");

		pane.add(table);
		f.add(pane);
		f.add(table);

		f.setVisible(true);
		f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}

}
```


----------

