This week's book giveaway is in the JavaScript forum.
We're giving away four copies of JavaScript Promises Essentials and have Rami Sarieddine on-line!
See this thread for details.
The moose likes Swing / AWT / SWT and the fly likes TableRenderer with multiple lines of text Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of JavaScript Promises Essentials this week in the JavaScript forum!
JavaRanch » Java Forums » Java » Swing / AWT / SWT
Bookmark "TableRenderer with multiple lines of text" Watch "TableRenderer with multiple lines of text" New topic
Author

TableRenderer with multiple lines of text

Ken Blair
Ranch Hand

Joined: Jul 15, 2003
Posts: 1078
I'm displaying a JTable in a modal JDialog, one of the fields is an address. I want to show the address as two to three lines, just as it would appear on a letter. I created a custom TableCellRenderer that uses a JTextArea and it seems to work if I insert the line breaks.

The problem is the row height doesn't change. I'm not sure what to do with this. Each row may have a different height as it could be anywhere from 1 to 3 lines of text (1 if there is no address to show, 3 if there's two address lines plus the city, state zip).

Furthermore, as a question on top of that. What's the best way to make the JDialog resize to show x number of rows? The size it needs to be to accomodate this is going to change as the user scrolls through them, or moves through with keys, as the row heights will vary.
H Lander
Greenhorn

Joined: Oct 23, 2005
Posts: 15
The height of each row in a JTable is by default fixed (16 pixels). In your table you have to specify the height of each row using the setRowHeight(int row, int rowHeight) method. If you know how many lines are in the row, then you can probably do this from the TableCellRenderer (not sure though as I have not actually done it).

I would recommend against the idea of changing the height of the dialog as the user scrolls down the table. It would probably not work well (other than to irritate the user of your dialog).

Good Luck,
Henry
Ken Blair
Ranch Hand

Joined: Jul 15, 2003
Posts: 1078
I'm not sure how to ascertain the appropriate row height. Can I just set it to the height of the JTextArea being used? I don't think that would work as the borders need to be included don't they?
H Lander
Greenhorn

Joined: Oct 23, 2005
Posts: 15
You can do the following on the Text Area:
theTextArea.getPreferredSize().height
That takes into account the space required for the borders.

However, I wouldn't recommend that as it would slow down the painting of the table. I would recommend, that you find out how much height each line requires by trial and error. Assuming that 18 pixels is appropriate, then set the row height to either 18, 36, or 54 based on the number of lines in the address. If the Text Area has a border, then add the space required at the top and bottom for the border.

Good Luck,
Henry
Ken Blair
Ranch Hand

Joined: Jul 15, 2003
Posts: 1078
Trial and error isn't a solution. If I do that the results are unpredictable when used on different operating systems with different look and feels or with a different font or font size.
Michael Dunn
Ranch Hand

Joined: Jun 09, 2003
Posts: 4632
this might be worth a read

http://www.javaspecialists.co.za/archive/Issue106.html
Ken Blair
Ranch Hand

Joined: Jul 15, 2003
Posts: 1078
Michael: I'm printing it out now so I can read it back at my desk but at a quick glance it looks like exactly what I needed. Where do you find these gems?
Michael Dunn
Ranch Hand

Joined: Jun 09, 2003
Posts: 4632
these ones I subscribe to - they are always a good (and informative) read
Ken Blair
Ranch Hand

Joined: Jul 15, 2003
Posts: 1078
Yeah, I don't like his code in this particular instance, it seems needlessly inefficient in many places. However, he seems to have a pretty darn good head on his shoulders and his methodology gave me some of the ideas/answers I needed. I will post my solution, or at least an incarnation of it, when I'm done for anyone interested.
Alejandro Barrero
Ranch Hand

Joined: Aug 01, 2005
Posts: 319
For some strange reason, the solution is to use a scroll box that contains a text area. here is the code:


import java.awt.Component;
import java.awt.Font;
import java.awt.FontMetrics;

import javax.swing.BorderFactory;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.table.TableCellRenderer;
/**
* This class is a JTextArea renderer for JTables. Traditionally, the idea did
* not work because the preferred size for the JTextArea returned at line<p>
* jTable.setRowHeight(row, (int)getPreferredSize().getHeight());<p>
* was the height of the column. Fortunately, for some reason, everything works
* if the renderer extends JScrollPane.
*
*/
public class TextAreaRenderer extends JScrollPane implements TableCellRenderer {
JTextArea jTextArea = new JTextArea();
/**
* Constructor.
*/
public TextAreaRenderer() {
this.jTextArea.setLineWrap(true);
this.jTextArea.setWrapStyleWord(true);
this.jTextArea.setFont(new Font("Dialog", Font.PLAIN, 12));
setBorder(BorderFactory.createEmptyBorder());
setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);
getVerticalScrollBar().setFocusable(false);
getHorizontalScrollBar().setFocusable(false);
setViewportView(this.jTextArea);
}

/**
* @see
* javax.swing.table.TableCellRenderer#getTableCellRendererComponent(javax.swing.JTable,
* java.lang.Object, boolean, boolean, int, int)
*/
public Component getTableCellRendererComponent(JTable jTable, Object obj,
boolean isSelected, boolean hasFocus, int row, int column) {
//Get the length of the text.
String displayString = (String)obj;
this.jTextArea.setText(displayString);
FontMetrics fontMetrics = this.jTextArea.getFontMetrics(this.jTextArea.getFont());
int textLength = SwingUtilities.computeStringWidth(fontMetrics, displayString);
//Compute the height.
int width = jTable.getColumnModel().getColumn(column).getWidth();
int numberOfRows = textLength/width;
if (numberOfRows*width < textLength)
numberOfRows++;
this.jTextArea.setRows(numberOfRows);
int rowHeight = (int)getPreferredSize().getHeight();
if (jTable.getRowHeight(row) < rowHeight)
jTable.setRowHeight(row, rowHeight);
return this;
}
}


Your help will be greatly appreciated,
Alejandro Barrero
Ken Blair
Ranch Hand

Joined: Jul 15, 2003
Posts: 1078
That won't work very well and not in the way I need it to. For one thing, the row can never get smaller. What happens if a user expands the largest column? The row should be smaller, but it won't be. I traced JTextArea's odd behavior down to BasicTextUI and some other behind the scenes Swing classes. Basically, when the preferred size hasn't been calculated yet it ends up looking at the size, which usually hasn't been set yet either. The natural inclination is the set the size to the width and leave height at 0, but that won't work because the offending class checks both height and width and uses NEITHER if EITHER are <= 0. This leads to an incorrect preferred size being calculated. This is the reason why setSize(columnWidth, Integer.MAX_VALUE) will work. Actually, setSize(columnWidth, insets.top + insets.bottom + 1) will work as well, it just needs to be taller than it's insets and it will function properly. JScrollPane likely invokes code that ends up in a similar workaround happening.

This might even be a bug, I'm not sure and I don't have the time or inclination to see if this behavior was intended or not. I would have thought it'd still use the width if it were set even if the height weren't, and not discard both if either was too small. Maybe I'll have time to investigate the matter further some day, but at this ponit I'm just happy to have it done and working, even if I don't like the workaround.

Here's what I came up with. Note that this impelements alternating color schemes and fonts, which was something I needed and not directly relevent to this. It also suppors having multiple renderers in the same table because I needed some columsn to have specific row counts and wanted them truncated if they were too small for their text, others needed to wrap. Hence the need for a third party to coordiante their heights to determine the appropriate row height for the table.
Ken Blair
Ranch Hand

Joined: Jul 15, 2003
Posts: 1078


[ October 27, 2005: Message edited by: Ken Blair ]
[ October 27, 2005: Message edited by: Ken Blair ]
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: TableRenderer with multiple lines of text