|
From: Benoit X. (JIRA) <no...@at...> - 2005-09-19 10:44:40
|
TableUtils resizing columns should take into account all rows.
--------------------------------------------------------------
Key: RCP-189
URL: http://opensource.atlassian.com/projects/spring/browse/RCP-189
Project: Spring Framework Rich Client Project
Type: Improvement
Components: Helper Classes
Reporter: Benoit Xhenseval
Assigned to: Oliver Hutchison
Hi
As discussed at the end of post http://forum.springframework.org/viewtopic.php?t=8933 , the current implementation TableUtils.sizeColumnsToFitRowData(JTable) just looks at the first row. It is understandable if the table contains thousands of rows...
Here is an alternative solution; it takes 250ms on my old laptop (1GHz) to resize a table of 7 columsn and 2,000 rows.
[code]
/**
* Resize the columns based on the data contained in all rows and Header.
* The original width will be based on the value of the column header, and,
* will be expanded if at least one row requires more space. The column header
* size is slightly padded to allow for sorting icons (GlazedTableModel).
* @param table the table to resize
* @author Benoit Xhenseval (modified)
*/
public static void sizeColumnsToFitAllRowData(JTable table) {
// go through each column first to take the renderer.
for (int col = 0; col < table.getColumnCount(); col++) {
final TableColumnModel colModel = table.getColumnModel();
final TableModel model = table.getModel();
TableColumn column = colModel.getColumn(col);
TableCellRenderer r = colModel.getColumn(col).getCellRenderer();
// original width should be based on the size of the HEADER.
int cWidth = table.getTableHeader().getFontMetrics(table.getTableHeader().getFont()).stringWidth(
model.getColumnName(col) + "XXXX"); // we have added 'XXXX' to allow space for sorting icons.
for (int row = 0; row < table.getRowCount(); row++) {
if (r == null) {
Object val = table.getValueAt(row, col);
if (val != null) {
r = table.getDefaultRenderer(val.getClass());
}
}
if (r != null) {
Component c = r.getTableCellRendererComponent(table, table.getValueAt(row, col), false, false, 0,
col);
cWidth = Math.max(c.getPreferredSize().width, cWidth);
}
}
column.setPreferredWidth(cWidth + UIConstants.ONE_SPACE);
column.setWidth(cWidth);
}
int width = Math.min(table.getColumnModel().getTotalColumnWidth(), (int) (WindowUtils.getScreenWidth() * .75));
table.setPreferredScrollableViewportSize(new Dimension(width, 300));
}
[/code]
since the name is slightly different, could you add this method to the TableUtils? Thanks!
We have also experienced some optimizations by quickly going through the values of each row and simply doing a toString() to it, then picking up the row
where the string is the biggest and only try to render that row. It is not the most accurate method if you have some funny
rendering (say Date formatting that abbreviate a Date dramatically). But for big tables, it would be faster! For our example
of 2,000 rows & 7 columns, it is about 30% faster.
Here is the code, again, we have named the method slightly differently so they can co-exist:
[code]
public static void sizeColumnsToFitAllRowDataBasedOnStrings(JTable table) {
for (int col = 0; col < table.getColumnCount(); col++) {
final TableColumnModel colModel = table.getColumnModel();
final TableModel model = table.getModel();
TableColumn column = colModel.getColumn(col);
TableCellRenderer r = colModel.getColumn(col).getCellRenderer();
// original width should be based on the size of the HEADER.
int cWidth = table.getTableHeader().getFontMetrics(table.getTableHeader().getFont()).stringWidth(
model.getColumnName(col) + "XXXX"); // we have added 'XXXX' to allow space for sorting icons.
// now simply spot the row that has the biggest "string"
int maxStringLength = 0;
Object maxRowValue = null;
int maxRowIndex = 0;
for (int row = 0; row < table.getRowCount(); row++) {
Object value = table.getValueAt(row, col);
if (value != null) {
final int length = value.toString().length();
if (length > maxStringLength) {
maxStringLength = length;
maxRowValue = value;
maxRowIndex = row;
}
}
}
// and uses that row for the rendering.
if (r == null) {
Object val = table.getValueAt(maxRowIndex, col);
if (val != null) {
r = table.getDefaultRenderer(val.getClass());
}
}
if (r != null) {
Component c = r.getTableCellRendererComponent(table, maxRowValue, false, false, 0, col);
cWidth = Math.max(c.getPreferredSize().width, cWidth);
}
column.setPreferredWidth(cWidth + UIConstants.ONE_SPACE);
column.setWidth(cWidth);
}
int width = Math.min(table.getColumnModel().getTotalColumnWidth(), (int) (WindowUtils.getScreenWidth() * .75));
table.setPreferredScrollableViewportSize(new Dimension(width, 300));
}
[/code]
Please let me know if/when you could put this in CVS so I can remove my own class.
Many thanks.
Benoit
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
http://opensource.atlassian.com/projects/spring/secure/Administrators.jspa
-
For more information on JIRA, see:
http://www.atlassian.com/software/jira
|
|
From: Lieven D. (JIRA) <no...@sp...> - 2008-10-09 20:31:25
|
[ http://jira.springframework.org/browse/RCP-189?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Lieven Doclo updated RCP-189:
-----------------------------
Fix Version/s: 1.x
> TableUtils resizing columns should take into account all rows.
> --------------------------------------------------------------
>
> Key: RCP-189
> URL: http://jira.springframework.org/browse/RCP-189
> Project: Spring Framework Rich Client Project
> Issue Type: Improvement
> Components: Helper Classes
> Reporter: Benoit Xhenseval
> Assignee: Oliver Hutchison
> Fix For: 1.x
>
>
> Hi
> As discussed at the end of post http://forum.springframework.org/viewtopic.php?t=8933 , the current implementation TableUtils.sizeColumnsToFitRowData(JTable) just looks at the first row. It is understandable if the table contains thousands of rows...
> Here is an alternative solution; it takes 250ms on my old laptop (1GHz) to resize a table of 7 columsn and 2,000 rows.
> [code]
> /**
> * Resize the columns based on the data contained in all rows and Header.
> * The original width will be based on the value of the column header, and,
> * will be expanded if at least one row requires more space. The column header
> * size is slightly padded to allow for sorting icons (GlazedTableModel).
> * @param table the table to resize
> * @author Benoit Xhenseval (modified)
> */
> public static void sizeColumnsToFitAllRowData(JTable table) {
> // go through each column first to take the renderer.
> for (int col = 0; col < table.getColumnCount(); col++) {
> final TableColumnModel colModel = table.getColumnModel();
> final TableModel model = table.getModel();
> TableColumn column = colModel.getColumn(col);
> TableCellRenderer r = colModel.getColumn(col).getCellRenderer();
> // original width should be based on the size of the HEADER.
> int cWidth = table.getTableHeader().getFontMetrics(table.getTableHeader().getFont()).stringWidth(
> model.getColumnName(col) + "XXXX"); // we have added 'XXXX' to allow space for sorting icons.
> for (int row = 0; row < table.getRowCount(); row++) {
> if (r == null) {
> Object val = table.getValueAt(row, col);
> if (val != null) {
> r = table.getDefaultRenderer(val.getClass());
> }
> }
> if (r != null) {
> Component c = r.getTableCellRendererComponent(table, table.getValueAt(row, col), false, false, 0,
> col);
> cWidth = Math.max(c.getPreferredSize().width, cWidth);
> }
> }
> column.setPreferredWidth(cWidth + UIConstants.ONE_SPACE);
> column.setWidth(cWidth);
> }
> int width = Math.min(table.getColumnModel().getTotalColumnWidth(), (int) (WindowUtils.getScreenWidth() * .75));
> table.setPreferredScrollableViewportSize(new Dimension(width, 300));
> }
> [/code]
> since the name is slightly different, could you add this method to the TableUtils? Thanks!
> We have also experienced some optimizations by quickly going through the values of each row and simply doing a toString() to it, then picking up the row
> where the string is the biggest and only try to render that row. It is not the most accurate method if you have some funny
> rendering (say Date formatting that abbreviate a Date dramatically). But for big tables, it would be faster! For our example
> of 2,000 rows & 7 columns, it is about 30% faster.
> Here is the code, again, we have named the method slightly differently so they can co-exist:
> [code]
> public static void sizeColumnsToFitAllRowDataBasedOnStrings(JTable table) {
> for (int col = 0; col < table.getColumnCount(); col++) {
> final TableColumnModel colModel = table.getColumnModel();
> final TableModel model = table.getModel();
> TableColumn column = colModel.getColumn(col);
> TableCellRenderer r = colModel.getColumn(col).getCellRenderer();
> // original width should be based on the size of the HEADER.
> int cWidth = table.getTableHeader().getFontMetrics(table.getTableHeader().getFont()).stringWidth(
> model.getColumnName(col) + "XXXX"); // we have added 'XXXX' to allow space for sorting icons.
> // now simply spot the row that has the biggest "string"
> int maxStringLength = 0;
> Object maxRowValue = null;
> int maxRowIndex = 0;
> for (int row = 0; row < table.getRowCount(); row++) {
> Object value = table.getValueAt(row, col);
> if (value != null) {
> final int length = value.toString().length();
> if (length > maxStringLength) {
> maxStringLength = length;
> maxRowValue = value;
> maxRowIndex = row;
> }
> }
> }
> // and uses that row for the rendering.
> if (r == null) {
> Object val = table.getValueAt(maxRowIndex, col);
> if (val != null) {
> r = table.getDefaultRenderer(val.getClass());
> }
> }
> if (r != null) {
> Component c = r.getTableCellRendererComponent(table, maxRowValue, false, false, 0, col);
> cWidth = Math.max(c.getPreferredSize().width, cWidth);
> }
> column.setPreferredWidth(cWidth + UIConstants.ONE_SPACE);
> column.setWidth(cWidth);
> }
> int width = Math.min(table.getColumnModel().getTotalColumnWidth(), (int) (WindowUtils.getScreenWidth() * .75));
> table.setPreferredScrollableViewportSize(new Dimension(width, 300));
> }
> [/code]
> Please let me know if/when you could put this in CVS so I can remove my own class.
> Many thanks.
> Benoit
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://jira.springframework.org/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
|