# JTable Spalten automatisch dem Inhalt anpassen!



## infboy (29. Dez 2012)

Hallo,

ich bastele gerade an einem einfachen Programm und möchte das die Spalten meiner Tabelle sich automatischen dem größten Inhalt anpassen. Habe schon zwar im net eine komplizierte Klasse gefunden die das macht, möchte es aber möglichst einfach und auch selbst machen.
Weiß vllt. jemand wie das geht? 

die gefundene Klasse im Net sieht so aus!

```
import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;

/*
 *	Class to manage the widths of colunmns in a table.
 *
 *  Various properties control how the width of the column is calculated.
 *  Another property controls whether column width calculation should be dynamic.
 *  Finally, various Actions will be added to the table to allow the user
 *  to customize the functionality.
 *
 *  This class was designed to be used with tables that use an auto resize mode
 *  of AUTO_RESIZE_OFF. With all other modes you are constrained as the width
 *  of the columns must fit inside the table. So if you increase one column, one
 *  or more of the other columns must decrease. Because of this the resize mode
 *  of RESIZE_ALL_COLUMNS will work the best.
 */
public class TableColumnAdjuster implements PropertyChangeListener, TableModelListener
{
	private JTable table;
	private int spacing;
	private boolean isColumnHeaderIncluded;
	private boolean isColumnDataIncluded;
	private boolean isOnlyAdjustLarger;
	private boolean isDynamicAdjustment;
	private Map<TableColumn, Integer> columnSizes = new HashMap<TableColumn, Integer>();

	/*
	 *  Specify the table and use default spacing
	 */
	public TableColumnAdjuster(JTable table)
	{
		this(table, 6);
	}

	/*
	 *  Specify the table and spacing
	 */
	public TableColumnAdjuster(JTable table, int spacing)
	{
		this.table = table;
		this.spacing = spacing;
		setColumnHeaderIncluded( true );
		setColumnDataIncluded( true );
		setOnlyAdjustLarger( true );
		setDynamicAdjustment( false );
		installActions();
	}

	/*
	 *  Adjust the widths of all the columns in the table
	 */
	public void adjustColumns()
	{
		TableColumnModel tcm = table.getColumnModel();

		for (int i = 0; i < tcm.getColumnCount(); i++)
		{
			adjustColumn(i);
		}
	}

	/*
	 *  Adjust the width of the specified column in the table
	 */
	public void adjustColumn(final int column)
	{
		TableColumn tableColumn = table.getColumnModel().getColumn(column);

		if (! tableColumn.getResizable()) return;

		int columnHeaderWidth = getColumnHeaderWidth( column );
		int columnDataWidth   = getColumnDataWidth( column );
		int preferredWidth    = Math.max(columnHeaderWidth, columnDataWidth);

		updateTableColumn(column, preferredWidth);
	}

	/*
	 *  Calculated the width based on the column name
	 */
	private int getColumnHeaderWidth(int column)
	{
		if (! isColumnHeaderIncluded) return 0;

		TableColumn tableColumn = table.getColumnModel().getColumn(column);
		Object value = tableColumn.getHeaderValue();
		TableCellRenderer renderer = tableColumn.getHeaderRenderer();

		if (renderer == null)
		{
			renderer = table.getTableHeader().getDefaultRenderer();
		}

		Component c = renderer.getTableCellRendererComponent(table, value, false, false, -1, column);
		return c.getPreferredSize().width;
	}

	/*
	 *  Calculate the width based on the widest cell renderer for the
	 *  given column.
	 */
	private int getColumnDataWidth(int column)
	{
		if (! isColumnDataIncluded) return 0;

		int preferredWidth = 0;
		int maxWidth = table.getColumnModel().getColumn(column).getMaxWidth();

		for (int row = 0; row < table.getRowCount(); row++)
		{
    		preferredWidth = Math.max(preferredWidth, getCellDataWidth(row, column));

			//  We've exceeded the maximum width, no need to check other rows

			if (preferredWidth >= maxWidth)
			    break;
		}

		return preferredWidth;
	}

	/*
	 *  Get the preferred width for the specified cell
	 */
	private int getCellDataWidth(int row, int column)
	{
		//  Inovke the renderer for the cell to calculate the preferred width

		TableCellRenderer cellRenderer = table.getCellRenderer(row, column);
		Component c = table.prepareRenderer(cellRenderer, row, column);
		int width = c.getPreferredSize().width + table.getIntercellSpacing().width;

		return width;
	}

	/*
	 *  Update the TableColumn with the newly calculated width
	 */
	private void updateTableColumn(int column, int width)
	{
		final TableColumn tableColumn = table.getColumnModel().getColumn(column);

		if (! tableColumn.getResizable()) return;

		width += spacing;

		//  Don't shrink the column width

		if (isOnlyAdjustLarger)
		{
			width = Math.max(width, tableColumn.getPreferredWidth());
		}

		columnSizes.put(tableColumn, new Integer(tableColumn.getWidth()));
		table.getTableHeader().setResizingColumn(tableColumn);
		tableColumn.setWidth(width);
	}

	/*
	 *  Restore the widths of the columns in the table to its previous width
	 */
	public void restoreColumns()
	{
		TableColumnModel tcm = table.getColumnModel();

		for (int i = 0; i < tcm.getColumnCount(); i++)
		{
			restoreColumn(i);
		}
	}

	/*
	 *  Restore the width of the specified column to its previous width
	 */
	private void restoreColumn(int column)
	{
		TableColumn tableColumn = table.getColumnModel().getColumn(column);
		Integer width = columnSizes.get(tableColumn);

		if (width != null)
		{
			table.getTableHeader().setResizingColumn(tableColumn);
			tableColumn.setWidth( width.intValue() );
		}
	}

	/*
	 *	Indicates whether to include the header in the width calculation
	 */
	public void setColumnHeaderIncluded(boolean isColumnHeaderIncluded)
	{
		this.isColumnHeaderIncluded = isColumnHeaderIncluded;
	}

	/*
	 *	Indicates whether to include the model data in the width calculation
	 */
	public void setColumnDataIncluded(boolean isColumnDataIncluded)
	{
		this.isColumnDataIncluded = isColumnDataIncluded;
	}

	/*
	 *	Indicates whether columns can only be increased in size
	 */
	public void setOnlyAdjustLarger(boolean isOnlyAdjustLarger)
	{
		this.isOnlyAdjustLarger = isOnlyAdjustLarger;
	}

	/*
	 *  Indicate whether changes to the model should cause the width to be
	 *  dynamically recalculated.
	 */
	public void setDynamicAdjustment(boolean isDynamicAdjustment)
	{
		//  May need to add or remove the TableModelListener when changed

		if (this.isDynamicAdjustment != isDynamicAdjustment)
		{
			if (isDynamicAdjustment)
			{
				table.addPropertyChangeListener( this );
				table.getModel().addTableModelListener( this );
			}
			else
			{
				table.removePropertyChangeListener( this );
				table.getModel().removeTableModelListener( this );
			}
		}

		this.isDynamicAdjustment = isDynamicAdjustment;
	}
//
//  Implement the PropertyChangeListener
//
	public void propertyChange(PropertyChangeEvent e)
	{
		//  When the TableModel changes we need to update the listeners
		//  and column widths

		if ("model".equals(e.getPropertyName()))
		{
			TableModel model = (TableModel)e.getOldValue();
			model.removeTableModelListener( this );

			model = (TableModel)e.getNewValue();
			model.addTableModelListener( this );
			adjustColumns();
		}
	}
//
//  Implement the TableModelListener
//
	public void tableChanged(TableModelEvent e)
	{
		if (! isColumnDataIncluded) return;

		//  A cell has been updated

		if (e.getType() == TableModelEvent.UPDATE)
		{
			int column = table.convertColumnIndexToView(e.getColumn());

			//  Only need to worry about an increase in width for this cell

			if (isOnlyAdjustLarger)
			{
				int	row = e.getFirstRow();
				TableColumn tableColumn = table.getColumnModel().getColumn(column);

				if (tableColumn.getResizable())
				{
					int width =	getCellDataWidth(row, column);
					updateTableColumn(column, width);
				}
			}

			//	Could be an increase of decrease so check all rows

			else
			{
				adjustColumn( column );
			}
		}

		//  The update affected more than one column so adjust all columns

		else
		{
			adjustColumns();
		}
	}

	/*
	 *  Install Actions to give user control of certain functionality.
	 */
	private void installActions()
	{
		installColumnAction(true,  true,  "adjustColumn",   "control ADD");
		installColumnAction(false, true,  "adjustColumns",  "control shift ADD");
		installColumnAction(true,  false, "restoreColumn",  "control SUBTRACT");
		installColumnAction(false, false, "restoreColumns", "control shift SUBTRACT");

		installToggleAction(true,  false, "toggleDynamic",  "control MULTIPLY");
		installToggleAction(false, true,  "toggleLarger",   "control DIVIDE");
	}

	/*
	 *  Update the input and action maps with a new ColumnAction
	 */
	private void installColumnAction(
		boolean isSelectedColumn, boolean isAdjust, String key, String keyStroke)
	{
		Action action = new ColumnAction(isSelectedColumn, isAdjust);
		KeyStroke ks = KeyStroke.getKeyStroke( keyStroke );
		table.getInputMap().put(ks, key);
		table.getActionMap().put(key, action);
	}

	/*
	 *  Update the input and action maps with new ToggleAction
	 */
	private void installToggleAction(
		boolean isToggleDynamic, boolean isToggleLarger, String key, String keyStroke)
	{
		Action action = new ToggleAction(isToggleDynamic, isToggleLarger);
		KeyStroke ks = KeyStroke.getKeyStroke( keyStroke );
		table.getInputMap().put(ks, key);
		table.getActionMap().put(key, action);
	}

	/*
	 *  Action to adjust or restore the width of a single column or all columns
	 */
	class ColumnAction extends AbstractAction
	{
    	private boolean isSelectedColumn;
    	private boolean isAdjust;

		public ColumnAction(boolean isSelectedColumn, boolean isAdjust)
		{
			this.isSelectedColumn = isSelectedColumn;
			this.isAdjust = isAdjust;
		}

		@Override
		public void actionPerformed(ActionEvent e)
		{
			//  Handle selected column(s) width change actions

			if (isSelectedColumn)
			{
				int[] columns = table.getSelectedColumns();

				for (int i = 0; i < columns.length; i++)
				{
					if (isAdjust)
						adjustColumn(columns[i]);
					else
						restoreColumn(columns[i]);
				}
			}
			else
			{
				if (isAdjust)
					adjustColumns();
				else
					restoreColumns();
			}
		}
	}

	/*
	 *  Toggle properties of the TableColumnAdjuster so the user can
	 *  customize the functionality to their preferences
	 */
	class ToggleAction extends AbstractAction
	{
		private boolean isToggleDynamic;
		private boolean isToggleLarger;

		public ToggleAction(boolean isToggleDynamic, boolean isToggleLarger)
		{
			this.isToggleDynamic = isToggleDynamic;
			this.isToggleLarger = isToggleLarger;
		}

		@Override
		public void actionPerformed(ActionEvent e)
		{
			if (isToggleDynamic)
			{
				setDynamicAdjustment(! isDynamicAdjustment);
				return;
			}

			if (isToggleLarger)
			{
				setOnlyAdjustLarger(! isOnlyAdjustLarger);
				return;
			}
		}
	}
}
```


----------



## bERt0r (29. Dez 2012)

Das ist doch bereits sehr einfach und übersichtlich: Wir finden heraus wie groß die größte Zelle bzw. der Header in einer Spalte ist und setzen die Breite der Spalte auf diese Größe. Das machen wir bei allen Spalten.


----------



## infboy (29. Dez 2012)

Kann man das nicht iwi in dem JTable machen oder wenn man ein extra AbstractTableModel hat dort das iwi erledigen?


----------



## bERt0r (29. Dez 2012)

iwi geht alles. Wenn du dir die Arbeit antun willst, schaffst du das schon.


----------



## L-ectron-X (29. Dez 2012)

AutofitTableColumns ? Byte-Welt Wiki


----------



## grinquel (1. Jan 2013)

salü zsam,
ich hatte das gleiche Prob - das tut's

```
private void initColumnSizes(JTable table) {
    	TableColumn column = null;
    	Component comp = null;
        int headWidth = 0;
        int cellWidth = 0;

        TableCellRenderer render = table.getTableHeader().getDefaultRenderer();

        int colNum = table.getColumnCount();
        int rowNum = table.getRowCount();

        for (int i = 0; i < (colNum); i++) { // Loop über alle cols

        	column = table.getColumnModel().getColumn(i);
            comp = render.getTableCellRendererComponent(
                          null, column.getHeaderValue(),false, false, 0, 0);
            headWidth = comp.getPreferredSize().width; 

            cellWidth = 50; // gewünschte Mindestbreite
            
            for (int j=0; j<(rowNum); j++){ // Loop über alle rows

                comp = render.getTableCellRendererComponent(
            			table, table.getValueAt(j, i), false, false, j, i);
            	cellWidth = Math.max(cellWidth, comp.getPreferredSize().width);
            }
            column.setPreferredWidth(Math.max(headWidth, cellWidth)+20);
        }   // was ist breiter Kopf oder Zellen // +20 etwas breiter (opt. Polster)
    }
```
a guats Neus


----------



## Holger_Anfänger (1. Jan 2013)

Hallo, habe das mal eben ausprobiert.

Die meisten Zellen werden angepasst. Allerdings wenn ich einen Satz wie diesen am Stück eingebe

tingel tangel bob kostete es einmal seinen job

dann erscheint

tingel tangel bob kostete es einmal...


Wenn ich den Satz Stück für Stück eintrage, dann wird immer Sauber die Breite angepasst.




Holger


----------

