Easy to Learn Java: Programming Articles, Examples and Tips

Start with Java in a few days with Java Lessons or Lectures

Home

Code Examples

Java Tools

More Java Tools!

Java Forum

All Java Tips

Books

Submit News
Search the site here...
Search...
 
Search the JavaFAQ.nu
1000 Java Tips ebook

1000 Java Tips - Click here for the high resolution copy!1000 Java Tips - Click here for the high resolution copy!

Java Screensaver, take it here

Free "1000 Java Tips" eBook is here! It is huge collection of big and small Java programming articles and tips. Please take your copy here.

Take your copy of free "Java Technology Screensaver"!.

Multi-line cells in the JTable

JavaFAQ Home » Story by Dr. Kabutz Go to all tips in Story by Dr. Kabutz


Bookmark and Share

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

Author: Dr. Heinz M. Kabutz

JDK version:

Category: GUI

You can subscribe from our home page: http://www.javaspecialists.co.za (which also hosts all previous issues, available free of charge Smile

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 Wink"

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


Copyright 2000-2004 Maximum Solutions, South Africa

Reprint Rights. Copyright subsists in all the material included in this email, but you may freely share the entire email with anyone you feel may be interested, and you may reprint excerpts both online and offline provided that you acknowledge the source as follows: This material from The Java(tm) Specialists' Newsletter by Maximum Solutions (South Africa). Please contact Maximum Solutions for more information.

Java and Sun are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries. Maximum Solutions is independent of Sun Microsystems, Inc.

 Printer Friendly Page  Printer Friendly Page
 Send to a Friend  Send to a Friend

.. Bookmark and Share

Search here again if you need more info!
Custom Search



Home Code Examples Java Forum All Java Tips Books Submit News, Code... Search... Offshore Software Tech Doodling

RSS feed Java FAQ RSS feed Java FAQ News     

    RSS feed Java Forums RSS feed Java Forums

All logos and trademarks in this site are property of their respective owner. The comments are property of their posters, all the rest 1999-2006 by Java FAQs Daily Tips.

Interactive software released under GNU GPL, Code Credits, Privacy Policy