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.
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 create a JTable at runtime. The number of columns will vary from a few to hundreds.
I have a database routine which populates a vector of vectors.
The topmost row is used as the header.
The data in the columns vary in size, and the column sizes are computed and set to the maximum width for that column. That is to say, each column will vary in size.
The table header in the table and the scroll pane are hidden via:
Common.myTBL.setTableHeader(null);
Common.myScrollPanel.setColumnHeaderView(null);
Common.myScrollPanel.setViewportView(Common.myTBL);
pack();
When the number of columns in the table is small - say 5 or 6 - I don't have any problems.
Common.myTBL.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_OFF);
But there is a particular case where the number of columns is 174 (0 to 173). The last column does not appear on the screen. I tried adding an extra dummy column (175th) and part of column 174 appeared.
This is the code that creates the Table Model and Table Object
public void createTableModel() {
int noOfColumns = 0;
int noOfRows = 0;
noOfRows = Common.tableData.size();
noOfColumns = Common.tableData.get(0).size();
System.out.println("\nNumber of Rows in the VECTOR = "+noOfRows);
System.out.println("\nNumber of columns in the VECTOR = "+noOfColumns);
Common.myTableModel = new AttributiveCellTableModel(noOfRows, noOfColumns);
System.out.println("\nNumber of Rows in the MODEL= "+Common.myTableModel.getRowCount());
System.out.println("\nNumber of columns in the MODEL = "+Common.myTableModel.getColumnCount());
Common.theRoots = Common.tableData.get(0);
Common.myTableModel.setDataVector(Common.tableData, Common.theRoots);
Common.cellAtt = (CellSpan)Common.myTableModel.getCellAttribute();
}
public void createTableObject() {
Common.myTBL = new MultiSpanCellTable(Common.myTableModel) {
public Component prepareRenderer(TableCellRenderer renderer, int Index_row, int Index_col) {
Component comp = super.prepareRenderer(renderer, Index_row, Index_col);
JComponent jcomp = (JComponent) comp;
Common.originalBorder = jcomp.getBorder();
comp.setBackground(setRowColor(Index_row));
jcomp.setToolTipText(getToolTip(Index_row, Index_col));
comp.setFont(Common.defaultFont14);
comp.setForeground(setGenderColor(Index_row, Index_col));
jcomp.setBorder(setBorderType(Index_row, Index_col));
return comp;
}
};
Common.myTBL.setRowHeight(25);
Common.myTBL.setBorder(null);
Common.myTBL.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_OFF);
Common.myTBL.setCellSelectionEnabled(true);
Common.myTBL.setGridColor(new java.awt.Color(0, 51, 255));
Common.myTBL.setFillsViewportHeight(true);
Common.myTBL.revalidate();
}
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.
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.