Home | JSP | EJB | JDBC | Java Servlets | WAP  | Free JSP Hosting  | Spring Framework | Web Services | BioInformatics | Java Server Faces | Jboss 3.0 tutorial | Hibernate 3.0 | XML

Tutorial Categories: Ajax | Articles | JSP | Bioinformatics | Database | Free Books | Hibernate | J2EE | J2ME | Java | JavaScript | JDBC | JMS | Linux | MS Technology | PHP | RMI | Web-Services | Servlets | Struts | UML


 

Search Host

Monthly Fee($)
Disk Space (MB)
Register With us for Newsletter!
Visit Forum! Post Questions!
Jobs At RoseIndia.net!

Have tutorials?
Add your tutorial to our Java Resource and get tons of hits.

We offer free hosting for your tutorials. and exposure for thousands of readers. drop a mail
roseindia_net@yahoo.com
 
   

Tutorials

Java Server Pages

JAXB

Java Beans

JDBC

MySQL

Java Servlets

Struts

Bioinformatics

Java Code Examples

Interview Questions

 
Join For Newsletter

Powered by groups.yahoo.com
Visit Group! Post Questions!

Web Promotion

Web Submission

Submit Sites

Manual Submission?

Web Promotion Guide

Hosting Companies

Web Hosting Guide

Web Hosting

Linux

Beginner Guide to Linux Server

Frameworks

Persistence Framework

Web Frameworks

Free EAI Tools

Web Servers

Aspect Oriented Programming

Free Proxy Servers

Softwares

Adware & Spyware Remover

Open Source Softwares

Multi-line cells in the JTable

       

2002-04-11 The Java Specialists' Newsletter [Issue 045] - Multi-line cells in the JTable

Author: Dr. Heinz M. Kabutz

If you are reading this, and have not subscribed, please consider doing it now by going to our subscribe page. You can subscribe either via email or RSS.


Welcome to the 45th edition of The Java(tm) Specialists' Newsletter, read in over 78 countries, with newest additions Thailand and Iceland. Both end with "land" but they couldn't be two more opposite countries. Why don't those drivers who insist on crawling along the German Autobahn at 140km/h stick to the slow lane? I drove almost 500km on Friday, and had the opportunity to meet Carl Smotricz (my archive keeper) and some other subscribers in Frankfurt. We had some very inspiring discussions regarding Java performance, enjoyed some laughs at Java's expense and listened to my tales of life in South Africa.

Unsubscription Fees: Some of my readers wrote to tell me what a fantastic idea unsubscription fees were to make some money. Others wrote angry notes asking how I had obtained their credit card details. All of them were wrong! Note the date of our last newsletter - 1st April! Yes, it was all part of the April Fool's craze that hits the world once a year. Apologies to those of you who found that joke in poor taste (my wife said I shouldn't put it in, but I didn't listen to her). The rest of the newsletter was quite genuine. A friend, who was caught "hook, line & sinker", suggested that I should clear things up and tell you exactly what my purpose is in publishing "The Java(tm) Specialists' Newsletter":

#1. Publishing this newsletter is my hobby: No idealism here at all. A friend encouraged me a few years ago to write down all the things I had been telling him about Java, so one day I simply started, and I have carried on doing it. It's a great way to relax, put the feet up and think a while.

#2. There are no subscription / unsubscription fees: The day that I'm so broke that I need to charge you for reading the things I write, will be the day that I immediately start looking for work as a permanent employee again. There are neither subscription nor unsubscription fees, nor will there ever be.

#3. How do I earn my living? Certainly not by writing newsletters! I spend about 75% of my time writing Java code on contract for customers situated in various parts of the world. 20% of my time is spent presenting Java and Design Patterns courses in interesting places such as Mauritius and South Africa and the last 5% is spent advising companies about Java technology.

#4. Marketing for Maximum Solutions: Because people know my company and me through this newsletter, I have received many requests for courses, contract work and consulting, and this helps me to make a living. My hobby of writing the newsletter has turned out to have some nice side effects.

And now, without wasting any more time, let's look at a real-life Java problem...

Multi-line cells in the JTable

The last slide of all my courses says that my students may send me questions any time they get stuck. A few weeks ago Robert Crida from Peralex in Bergvliet, South Africa, who came on my Java course last year, asked me how to display a JTextArea within a cell of a JTable. I sensed it would take more than 5 minutes to answer and being in a rush to finish some work inbetween Mauritius and Germany, I told him it would take me a few days to get back to him. When I got to Germany, I promptly forgot about his problem, until one of his colleagues reminded me last week.

Robert was trying to embed a JTextArea object within a JTable. The behaviour that he was getting was that when he resized the width of the table, he could see that the text in the text area was being wrapped onto multiple lines but the cells did not become higher to show those lines. He wanted the table row height to be increased automatically to make the complete text area visible.

He implemented a JTextArea cell renderer as below:

import java.awt.Component;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.table.TableCellRenderer;

public class TextAreaRenderer extends JTextArea
    implements TableCellRenderer {

  public TextAreaRenderer() {
    setLineWrap(true);
    setWrapStyleWord(true);
  }

  public Component getTableCellRendererComponent(JTable jTable,
      Object obj, boolean isSelected, boolean hasFocus, int row,
      int column) {
    setText((String)obj);
    return this;
  }
}

I wrote some test code to try this out. Before I continue, I need to point out that I use the SUN JDK 1.3.1 whereas Robert uses the SUN JDK 1.4.0. The classic "write once, debug everywhere" is a topic for another newsletter ...

import javax.swing.*;
import java.awt.BorderLayout;

public class TextAreaRendererTest extends JFrame {
  // The table has 10 rows and 3 columns
  private final JTable table = new JTable(10, 3);

  public TextAreaRendererTest() {
    // We use our cell renderer for the third column
    table.getColumnModel().getColumn(2).setCellRenderer(
      new TextAreaRenderer());
    // We hard-code the height of rows 0 and 5 to be 100
    table.setRowHeight(0, 100);
    table.setRowHeight(5, 100);
    // We put the table into a scrollpane and into a frame
    getContentPane().add(new JScrollPane(table));
    // We then set a few of the cells to our long example text
    String test = "The lazy dog jumped over the quick brown fox";
    table.getModel().setValueAt(test, 0, 0);
    table.getModel().setValueAt(test, 0, 1);
    table.getModel().setValueAt(test, 0, 2);
    table.getModel().setValueAt(test, 4, 0);
    table.getModel().setValueAt(test, 4, 1);
    table.getModel().setValueAt(test, 4, 2);
  }

  public static void main(String[] args) {
    TextAreaRendererTest test = new TextAreaRendererTest();
    test.setSize(600, 600);
    test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    test.show();
  }
}

You'll notice when you run this, that when the row is high enough the text wraps very nicely inside the JTextArea, as in cell (0, 2). However, the JTable does not increase the row height in cell (4, 2) just because you decide to put a tall component into the cell. It requires a bit of prodding to do that.

My first approach was to override getPreferredSize() in the TextAreaRenderer class. However, that didn't work because JTable didn't take your preferred size into account in sizing the rows. I spent about an hour delving through the source code of JTable and JTextArea. After a lot of experimentation, I found out that JTextArea actually had the correct preferred size according to the width of the column in the JTable. I tried changing the getTableCellRendererComponent() method:

  public Component getTableCellRendererComponent(JTable jTable,
      Object obj, boolean isSelected, boolean hasFocus, int row,
      int column) {
    setText((String)obj);
    table.setRowHeight(row, (int)getPreferredSize().getHeight());
    return this;
  }

On first glimpse, the program seemed to work correctly now, except that my poor CPU was running at 100%. The problem was that when you set the row height, the table was invalidated and that caused getTableCellRendererComponent() to be called in order to render all the cells again. This in turn then set the row height, which invalidated the table again. In order to put a stop to this cycle of invalidation, I needed to check whether the row is already the correct height before setting it:

  public Component getTableCellRendererComponent(JTable jTable,
      Object obj, boolean isSelected, boolean hasFocus, int row,
      int column) {
    setText((String)obj);
    int height_wanted = (int)getPreferredSize().getHeight();
    if (height_wanted != table.getRowHeight(row))
      table.setRowHeight(row, height_wanted);
    return this;
  }

I tried it out (on SUN JDK 1.3.1) and it worked perfectly. There are some restrictions with my solution:

  1. It will only work when only one column contains the TextAreaRenderer. You can easily write around this problem by having coordination between the various TextAreaRenderers.
  2. You need to implement a TextAreaEditor, which I imagine will actually be a lot easier.

Satisfied, I sent off the answer to Robert, with the words: "After spending an hour tearing out my hair, I found a solution for you, it's so simple you'll kick yourself, like I did myself ;-)"

A few hours the answer came back: "Your solution does not solve my problem at all."

"What?" I thought. Upon questioning his configuration, we realised that I was using JDK 1.3.1 and Robert was using JDK 1.4.0. I tried it on JDK 1.4.0 on my machine, and truly, it did not render properly! What had they changed so that it didn't work anymore? After battling for another hour trying to figure out what the difference was and why it didn't work out, I gave up and carried on with my other work of tuning someone's application server. If you know how to do it in JDK 1.4.0, please tell me!

I have avoided JDK 1.4 for real-life projects, because I prefer others to find the bugs first. Most of my work is spent programming on real-life projects, so JDK 1.3.1 is the version I'm stuck with. My suspicion of new JDK versions goes back to when I started using JDK 1.0.x, JDK 1.1.x, JDK 1.2.x. I found that for every bug that was fixed in a new major version, 3 more appeared, and I grew tired of being a guinea pig. I must admit that I'm very happy with JDK 1.3.1, as I was with JDK 1.2.2 and JDK 1.1.8. I think that once JDK 1.4.1 is released I'll start using it and then you'll see more newsletters about that version of Java.

In a future newsletter I will demonstrate how you can implement "friends" at runtime in the JDK 1.4.

Heinz


This material from The Java(tm) Specialists' Newsletter by Maximum Solutions (South Africa). Please contact Maximum Solutions for more information.

       

Useful Links
  JDO Tutorials
  EAI Articles
  Struts Tutorials
  Java Tutorials
  Java Certification
Tell A Friend
Your Friend Name
Search Tutorials

 

 
Browse all Java Tutorials
Java JSP Struts Servlets Hibernate XML
Ajax JDBC EJB MySQL JavaScript JSF
Maven2 Tutorial JEE5 Tutorial Java Threading Tutorial Photoshop Tutorials Linux Technology
Technology Revolutions Eclipse Spring Tutorial Bioinformatics Tutorials Tools SQL
 

Home | JSP | EJB | JDBC | Java Servlets | WAP  | Free JSP Hosting  | Search Engine | News Archive | Jboss 3.0 tutorial | Free Linux CD's | Forum | Blogs

About Us | Advertising On RoseIndia.net

Send your comments, Suggestions or Queries regarding this site at roseindia_net@yahoo.com.

Copyright 2007. All rights reserved.