Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to wrap lines in a jtable cell?

Tags:

java

swing

jtable

I'm trying to implement a custom TableRenderer as described in this tutorial. I'd like to have the renderer line-wrap each text that is to long for the given cell. The idea is, to use a TextArea as renderer, as it supports line wrapping. However, the following code does not behave as expected:

public class LineWrapCellRenderer  extends JTextArea implements TableCellRenderer {      @Override     public Component getTableCellRendererComponent(             JTable table,             Object value,             boolean isSelected,             boolean hasFocus,             int row,             int column) {         this.setText((String)value);         this.setWrapStyleWord(true);                     this.setLineWrap(true);                  return this;     }  } 

I set this renderer with

table.setDefaultRenderer(String.class, new LineWrapCellRenderer()); 

But the cell entries stay unwrapped. If I add this.setBackground(Color.YELLOW) to the getTableCellRendererComponent() method, all cells are yellow as expected, but not wrapped.

Any ideas?

UPDATE: As Michael Borgwardt stated in the comments, the problem is not the line wrap, but the row height: JTables rows are fixed size, so if a cell is getting higher (cause the text is now multi-lined), we have to increase the row height. But how much? I will check if this is worth another SO-question. If not, I will add this solution here.

Update2: The following code will determine the row height (if placed in getTableCellRendererComponent()):

int fontHeight = this.getFontMetrics(this.getFont()).getHeight(); int textLength = this.getText().length(); int lines = textLength / this.getColumns() +1;//+1, cause we need at least 1 row.            int height = fontHeight * lines;             table.setRowHeight(row, height); 
like image 784
Arvodan Avatar asked Jun 08 '09 13:06

Arvodan


1 Answers

The problem is that the height of rows in JTable is fixed, so it's not just a matter of having a renderer that wraps; I'm not sure why it doesn't, but if it did, the wrapped text would be cropped - or maybe that's exactly what you're seeing. To adjust row heights, you need to set them individually.

Heres' some code for that:

int rows = 10; int cols = 5; JTable table = new JTable(rows, cols);  // Set the 1st row to 60 pixels high table.setRowHeight(0, 60);  // Set the height of all rows to 32 pixels high, // regardless if any heights were assigned to particular rows table.setRowHeight(32); // the height of the 1st row is set to 32 pixels high  // Returns the preferred height of a row. // The result is equal to the tallest cell in the row. public int getPreferredRowHeight(JTable table, int rowIndex, int margin) {     // Get the current default height for all rows     int height = table.getRowHeight();      // Determine highest cell in the row     for (int c=0; c<table.getColumnCount(); c++) {         TableCellRenderer renderer = table.getCellRenderer(rowIndex, c);         Component comp = table.prepareRenderer(renderer, rowIndex, c);         int h = comp.getPreferredSize().height + 2*margin;         height = Math.max(height, h);     }     return height; }  // The height of each row is set to the preferred height of the // tallest cell in that row. public void packRows(JTable table, int margin) {     packRows(table, 0, table.getRowCount(), margin); }  // For each row >= start and < end, the height of a // row is set to the preferred height of the tallest cell // in that row. public void packRows(JTable table, int start, int end, int margin) {     for (int r=0; r<table.getRowCount(); r++) {         // Get the preferred height         int h = getPreferredRowHeight(table, r, margin);          // Now set the row height using the preferred height         if (table.getRowHeight(r) != h) {             table.setRowHeight(r, h);         }     } } 
like image 116
Michael Borgwardt Avatar answered Oct 04 '22 11:10

Michael Borgwardt