I am trying to match the JTable column width depending on the data inside. My Code:
for(int column = 0; column < gui.testsuiteInfoTable.getColumnCount(); column ++){
int width =0;
for (int row = 0; row < gui.testsuiteInfoTable.getRowCount(); row++) {
TableCellRenderer renderer = gui.testsuiteInfoTable.getCellRenderer(row, column);
Component comp = gui.testsuiteInfoTable.prepareRenderer(renderer, row, column);
width = Math.max (comp.getPreferredSize().width, width);
System.out.println(width);
}
TableColumn col = new TableColumn();
col = gui.testsuiteInfoTable.getColumnModel().getColumn(column);
System.out.println(width);
col.setWidth(width);
gui.testsuiteInfoTable.revalidate();
}
}
The sizes are correct I guess but the table columns still all have the same width! The table is embedded in a ScrollPane in a GridBagLayout is that the problem? Thanks for any suggestions.
This is all you need:
JTable table = new JTable(){
#Override
public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
Component component = super.prepareRenderer(renderer, row, column);
int rendererWidth = component.getPreferredSize().width;
TableColumn tableColumn = getColumnModel().getColumn(column);
tableColumn.setPreferredWidth(Math.max(rendererWidth + getIntercellSpacing().width, tableColumn.getPreferredWidth()));
return component;
}
};
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
The table will adjust each column width automatically to fit the content. There's no need to control when to trigger the resizing.
If you can use an extra library, try Swingx (https://java.net/projects/swingx)
There you have a JXTable, with a method "packAll()", that does exactly what you are asking for
col.setWidth(width);
Read the JTable API and follow the link on How to Use Tables. In that tutorial they use the setPreferredWidth(...) to suggest a width for a column.
You may also want to check out the Table Column Adjuster which does this for you. This solution can also take into account the width of the column header.
Related
i have a DefaultTableModel:
DefaultTableModel model = new DefaultTableModel(data, beschriftung)
{
// Returning the Class of each column will allow different
// renderers to be used based on Class
public Class getColumnClass(int column)
{
return getValueAt(0, column).getClass();
}
};
This is inside a table:
JTable table = new JTable(model);
table.setEnabled(false);
table.setRowHeight(50);
And the table is inside a scrollPane:
JScrollPane scrollPane = new JScrollPane(table);
scrollPane.setBounds(1215, 11, 300, 300);
scrollPane.setWheelScrollingEnabled(true);
scrollPane.setEnabled(false);
getContentPane().add(scrollPane);
I have two rows, but want the first one to be shorter than the second one. Any suggestions?
This is how it looks like:
This is how I want it to look like:
Check out:
Check of the section from the Swing tutorial on Setting and Changing Columns Widths. It shows how you can manually set a preferred size for each column.
The basic code would be:
table.getColumnModel().getColumn(???).setPreferredWidth(???)
You can also check out the Table Column Adjuster for automatic sizing of columns based on the data contained in the model
The basic code for this approach is:
JTable table = new JTable( ... );
table.setAutoResizeMode( JTable.AUTO_RESIZE_OFF );
for (int column = 0; column < table.getColumnCount(); column++)
{
TableColumn tableColumn = table.getColumnModel().getColumn(column);
int preferredWidth = tableColumn.getMinWidth();
int maxWidth = tableColumn.getMaxWidth();
for (int row = 0; row < table.getRowCount(); row++)
{
TableCellRenderer cellRenderer = table.getCellRenderer(row, column);
Component c = table.prepareRenderer(cellRenderer, row, column);
int width = c.getPreferredSize().width + table.getIntercellSpacing().width;
preferredWidth = Math.max(preferredWidth, width);
// We've exceeded the maximum width, no need to check other rows
if (preferredWidth >= maxWidth)
{
preferredWidth = maxWidth;
break;
}
}
tableColumn.setPreferredWidth( preferredWidth );
}
The TableColumnAdjuster class in the link contains other features as well.
Also check out the JTable API for the setAutoResizeMode(...) method to determine how space is allocated if the width of the table changes.
My table cell center its value because i use a custom rendered like this..
public static void setCellsAlignment(JTable table, int alignment) {
DefaultTableCellRenderer rightRenderer = new DefaultTableCellRenderer();
rightRenderer.setHorizontalAlignment(alignment);
rightRenderer.setVerticalAlignment(alignment);
TableModel tableModel = table.getModel();
for (int columnIndex = 0; columnIndex < tableModel.getColumnCount(); columnIndex++) {
table.getColumnModel().getColumn(columnIndex).setCellRenderer(rightRenderer);
}
}
Use in Table..
setCellsAlignment(table, SwingConstants.CENTER);
This give me perfect center value of table ..
But problem is when i want to edit a cell, it start from beginning. But i want to edit also from center...
I have the following JTable (Actually it's a ETable from Netbeans). It stretches across the container it's in - I'd like to keep that, and not use JTable.AUTO_RESIZE_OFF
I'd like to fit it programatically like below, resizing each column to fit the only the cell content, or column header text and having the rightmost column fill the remaining space. How can I do that ?
You do have to set autoResize to OFF (setAutoResizeMode(JTable.AUTO_RESIZE_OFF);), but you also need a helper method to resize your columns.
This is inside a custom class that extends JTable, but you can just as easily reference an existing JTable:
public void resizeColumnWidth() {
int cumulativeActual = 0;
int padding = 15;
for (int columnIndex = 0; columnIndex < getColumnCount(); columnIndex++) {
int width = 50; // Min width
TableColumn column = columnModel.getColumn(columnIndex);
for (int row = 0; row < getRowCount(); row++) {
TableCellRenderer renderer = getCellRenderer(row, columnIndex);
Component comp = prepareRenderer(renderer, row, columnIndex);
width = Math.max(comp.getPreferredSize().width + padding, width);
}
if (columnIndex < getColumnCount() - 1) {
column.setPreferredWidth(width);
cumulativeActual += column.getWidth();
} else { //LAST COLUMN
//Use the parent's (viewPort) width and subtract the previous columbs actual widths.
column.setPreferredWidth((int) getParent().getSize().getWidth() - cumulativeActual);
}
}
}
Call resizeColumnWidth() whenever you add a row.
Optionally add a listener to the table so that the columns are also resized when the table itself is resized:
public MyCustomJTable() {
super();
addHierarchyBoundsListener(new HierarchyBoundsAdapter() {
#Override
public void ancestorResized(HierarchyEvent e) {
super.ancestorResized(e);
resizeColumnWidth();
}
});
setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
}
You can turn off auto resize. In this case the columns will resize automatically according to content. But in this case, if total column width is less than table's width, blank space will be there on right side. If it is greater, horizontal scroll bar will appear.
You can assign preferred width to each column using TableColumn.setPreferredWidth. Swing will try to distribute extra space according to that. But this is also not guaranteed.
I have a JTable that will have the last column data field change to different string values. I want to resize the column to the string length. What is the formula for string length to width?
I'm going to be using JTable.getColumnModel().getColumn().setPreferredWidth() so I want to know how to translate string length to width value.
you are not really interested in the string length (nor its mapping to a particular font/metrics). You're interested in the preferredSize of the renderingComponent which renderers the cell content. To get that, loop through all rows and query the size, something like
int width = 0;
for (row = 0; row < table.getRowCount(); row++) {
TableCellRenderer renderer = table.getCellRenderer(row, myColumn);
Component comp = table.prepareRenderer(renderer, row, myColumn);
width = Math.max (comp.getPreferredSize().width, width);
}
Or use JXTable (in the SwingX project): it has a method pack() which does the work for you :-)
Edit: the reason to prefer the table's prepareRenderer over manually calling getXXRendererComponent on the renderer is that the table might do decorate visual properties of the renderingComponent. If those decorations effect the prefSize of the component, a manual config is off.
This method will pack a given column in a JTable -
/**
* Sets the preferred width of the visible column specified by vColIndex. The column
* will be just wide enough to show the column head and the widest cell in the column.
* margin pixels are added to the left and right
* (resulting in an additional width of 2*margin pixels).
*/
public static void packColumn(JTable table, int vColIndex, int margin) {
DefaultTableColumnModel colModel = (DefaultTableColumnModel)table.getColumnModel();
TableColumn col = colModel.getColumn(vColIndex);
int width = 0;
// Get width of column header
TableCellRenderer renderer = col.getHeaderRenderer();
if (renderer == null) {
renderer = table.getTableHeader().getDefaultRenderer();
}
java.awt.Component comp = renderer.getTableCellRendererComponent(
table, col.getHeaderValue(), false, false, 0, 0);
width = comp.getPreferredSize().width;
// Get maximum width of column data
for (int r=0; r<table.getRowCount(); r++) {
renderer = table.getCellRenderer(r, vColIndex);
comp = renderer.getTableCellRendererComponent(
table, table.getValueAt(r, vColIndex), false, false, r, vColIndex);
width = Math.max(width, comp.getPreferredSize().width);
}
// Add margin
width += 2*margin;
// Set the width
col.setPreferredWidth(width);
}
Table Column Adjuster works both statically and dynamically and the user can control this.
I have a table , where some objects are rendered and are of non-fixed size (list of attributes). I want each row to be as high as it's tallest object , and I was wondering of to do it. I thought about doing something like this (see below) , but I'm sure there's something better..
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected,
boolean hasFocus, int row,
int column)
{
/*....*/
this.setListData((Object[])value);
int height = new Double(getPreferredSize().getHeight()).intValue();
if (table.getRowHeight(row) < height)
table.setRowHeight(row, height);
/*....*/
return this;
}
You should not have code like that in a renderer. Instead, when you load the data into the model, do something like:
private void updateRowHeights()
{
try
{
for (int row = 0; row < table.getRowCount(); row++)
{
int rowHeight = table.getRowHeight();
for (int column = 0; column < table.getColumnCount(); column++)
{
Component comp = table.prepareRenderer(table.getCellRenderer(row, column), row, column);
rowHeight = Math.max(rowHeight, comp.getPreferredSize().height);
}
table.setRowHeight(row, rowHeight);
}
}
catch(ClassCastException e) {}
}
I would stick with the solution you have. I don't think there is a simpler way to do this. No matter what you are going to have the check the height of each cell, so you might as well do that as you render each one.