4

I have a JTextArea that I'm using as a cell renderer for a table. In the getTableCellRenderercomponent method I have:

    setText(getTextForCell());
    setSize(table.getColumnModel().getColumn(column).getWidth(), 0);
    getUI().getRootView(textArea).setSize(textArea.getWidth(), 0f);
    updateSize();


    private void updateSize() {
       int prefHeight = textArea.getPreferredSize().height;
       int currHeight = table.getRowHeight(r);
       if (prefHeight > currHeight) {
        table.setRowHeight(row, prefHeight);          
      }

When the text area uses wrap style word, it is sometimes a row short.

If I call this updateSize method from outside getTableCellRendererComponent then it works properly. But with a large table, calling update size on all rows whenever a column size adjusts is not feasible because it is too slow, so I've been trying to find a way to do the resize during the row rendering.

There is a related Java bug (that is marked as fixed but it does not appear that it really is) http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4446522, but this workaround does not appear to work when using word wrap.

Can anyone provide an alternative on how to make this work properly?

Jeff Storey
  • 56,312
  • 72
  • 233
  • 406

1 Answers1

7

An alternative works properly

enter image description here

import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
import javax.swing.text.*;

public class AutoWrapInJTable {

    public AutoWrapInJTable() {
        String[] columnNames = {"TextAreaCellRenderer"};
        Object[][] data = {
            {"123456789012345678901234567890"},
            {"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddx"},
            {"----------------------------------------------0"},
            {">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>|"},};
        TableModel model = new DefaultTableModel(data, columnNames) {

            private static final long serialVersionUID = 1L;

            @Override
            public boolean isCellEditable(int row, int column) {
                return false;
            }
        };
        JTable table = new JTable(model) {

            private static final long serialVersionUID = 1L;

            @Override
            public void doLayout() {
                TableColumn col = getColumnModel().getColumn(0);
                for (int row = 0; row < getRowCount(); row++) {
                    Component c = prepareRenderer(col.getCellRenderer(), row, 0);
                    if (c instanceof JTextArea) {
                        JTextArea a = (JTextArea) c;
                        int h = getPreferredHeight(a) + getIntercellSpacing().height;
                        if (getRowHeight(row) != h) {
                            setRowHeight(row, h);
                        }
                    }
                }
                super.doLayout();
            }//http://tips4java.wordpress.com/2008/10/26/text-utilities/

            private int getPreferredHeight(JTextComponent c) {
                Insets insets = c.getInsets();
                View view = c.getUI().getRootView(c).getView(0);
                int preferredHeight = (int) view.getPreferredSpan(View.Y_AXIS);
                return preferredHeight + insets.top + insets.bottom;
            }
        };
        table.setEnabled(false);
        table.setShowGrid(false);
        table.setTableHeader(null);
        table.getColumnModel().getColumn(0).setCellRenderer(new TextAreaCellRenderer());
        table.setPreferredScrollableViewportSize(table.getPreferredSize());
        JScrollPane sp = new JScrollPane(table);
        sp.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
        JPanel p = new JPanel(new BorderLayout());
        p.add(sp);
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        f.add(p);
        //f.pack();
        f.setSize(200, 200);
        f.setLocation(150, 150);
        f.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                AutoWrapInJTable autoWrapInJTable = new AutoWrapInJTable();
            }
        });
    }
}

class TextAreaCellRenderer extends JTextArea implements TableCellRenderer {

    private static final long serialVersionUID = 1L;
    private final Color evenColor = new Color(230, 240, 255);

    public TextAreaCellRenderer() {
        super();
        setLineWrap(true);
        setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
    }

    @Override
    public Component getTableCellRendererComponent(JTable table, Object value,
            boolean isSelected, boolean hasFocus, int row, int column) {
        if (isSelected) {
            setForeground(table.getSelectionForeground());
            setBackground(table.getSelectionBackground());
        } else {
            setForeground(table.getForeground());
            setBackground(table.getBackground());
            setBackground((row % 2 == 0) ? evenColor : getBackground());
        }
        setFont(table.getFont());
        setText((value == null) ? "" : value.toString());
        return this;
    }
}
mKorbel
  • 109,525
  • 20
  • 134
  • 319