0

I have a JTable with cells that have variable heights because of there Content. I accomplished this by using a JTextArea in my TableCellRenderer. I want to Color parts of the String in different colors. JTextPane supports HTML tags and text area doesn't but with text pane it is not possible to change the height of the cell.

Any idea how I can use variable cell heights and coloring of the string with JTable?

public class LineWrapCellRenderer extends JTextPane implements TableCellRenderer {

    int rowHeight = 0;  // current max row height for this scan
    final int paddingRight = 4;
    final int paddingLeft = 4;
    Border padding = BorderFactory.createEmptyBorder(5, paddingLeft, 5, paddingRight);


@Override
    public Component getTableCellRendererComponent(
            JTable table,
            Object value,
            boolean isSelected,
            boolean hasFocus,
            int row,
            int column){

        setContentType("text/html");
        setText(setHTML((String) value));
        setSelectionColor(Color.BLUE);


        this.setBorder(padding);//Abstände der Zeilen

        //markieren fals selektiert
        if (isSelected){
            setBackground(table.getSelectionBackground());
//          setForeground(table.getSelectionForeground());
        }
        else
        {
            setBackground(table.getBackground());
//          setForeground(table.getForeground());
        }

        // current table column width in pixels
        int colWidth = table.getColumnModel().getColumn(column).getWidth() + table.getIntercellSpacing().width;

        // set the text area width (height doesn't matter here)
        Dimension dim = new Dimension(colWidth, 1);
        setSize(dim);

        // get the text area preferred height and add the row margin
        int height = getPreferredSize().height + table.getRowMargin();


        // ensure the row height fits the cell with most lines
        if (height != table.getRowHeight(row)) {
            table.setRowHeight(row, height);
        }

        return this;
    }

using this code with JTextPane has no effect on the cell height. using the same code with JTextArea the height is adjusted.

lolung
  • 465
  • 3
  • 15
  • *"..but with JTextPane it is not possible to Change the height of the cell."* Isn't it? Is the HTML specifying a body width using CSS? – Andrew Thompson Nov 13 '14 at 07:46
  • @AndrewThompson _width_ and _height_ are not the same. – icza Nov 13 '14 at 07:52
  • @icza Well duh.. Nobody said they were. See [this answer](http://stackoverflow.com/a/7861833/418556) for how setting a *width* causes the component to have the desired *height.* – Andrew Thompson Nov 13 '14 at 07:57
  • For better help sooner, post an [MCVE](http://stackoverflow.com/help/mcve) (Minimal Complete Verifiable Example). – Andrew Thompson Nov 13 '14 at 08:02

1 Answers1

2

You can set/change the height of each individual row with the following method:

JTable.setRowHeight(int row, int rowHeight);

As for coloring parts of the text displayed in a cell, you can simply use HTML code, e.g.

String value = "<html>Following word is <font color=\"red\">RED</font>.</html>";

The default table cell renderer (DefaultTableCellRenderer) uses/extends JLabel which properly handles/accepts HTML code.

Manual height

See this example:

JFrame f = new JFrame("Test");

JTable t = new JTable();
((DefaultTableModel)t.getModel()).setDataVector(new Object[][]{
        {"<html>Next word is <font color=\"red\">RED</font>.</html>", "50px"},
        {"<html>Following  is <font color=\"blue\">BLUE</font>.<br><br>"
            + "Long lines are automatically wrapped"
            + " as this long line demonstrates it.</html>", "150px"},
}, new Object[]{"Formatted text","Height"});
t.setRowHeight(0, 50);
t.setRowHeight(1, 150);
f.add(new JScrollPane(t));

f.pack();
f.setVisible(true);

Result:

enter image description here

Packing / Authoheight

If you want to "pack" all your rows to have the minimum height the value requires, you can do it like this:

JFrame f = new JFrame("Test");

JTable t = new JTable();
((DefaultTableModel) t.getModel()).setDataVector(new Object[][] {
        {"<html>Next word is <font color='red'>RED</font>.</html>", "50px" },
        {"<html><body style='width:200px'>Following  is"
            + " <font color='blue'>BLUE</font>.<br><br>"
            + "Long lines are automatically wrapped "
            + "as this long line demonstrates it.</body></html>", "150px" }, },
        new Object[] {"Formatted text", "Height"});

for (int i = 0; i < t.getRowCount(); i++)
    t.setRowHeight(i, t.getCellRenderer(i, 0)
        .getTableCellRendererComponent(t, t.getValueAt(i, 0), false, false, i, 0)
            .getPreferredSize().height);

f.add(new JScrollPane(t));

f.pack();
f.setVisible(true);

Basically iterate over the rows, and ask the preferred height from the renderer, and set that as the row height.

Note: This required to set width style in HTML values that are auto-wrapped to multiple lines. If you don't do this, the preferred height of an HTML value will be the preferred height without auto-wrapping long lines (manual wrapping like <br> tags will still be considered).

This will result in this:

enter image description here

Chin
  • 16,446
  • 27
  • 96
  • 148
icza
  • 289,344
  • 42
  • 658
  • 630
  • using setRowHeight with JTextPane has no effect. it makes them so small that you can´t see any Content which is very weird. – lolung Nov 13 '14 at 08:04
  • @lolung Added an example with image to show `setRowHeight()` works, also included coloring. – icza Nov 13 '14 at 08:10
  • weird. tried to extend `DefaultTableCellRenderer` and set the height like in my code while Rendering but `getPreferredSize().height` is returning always the same height. – lolung Nov 13 '14 at 08:25
  • @lolung You shouldn't change row height from the renderer. Edited the answer to show how to "pack" the table to set the heights. – icza Nov 13 '14 at 08:59
  • iterating the cells is working fine. My table can get very large and iterating can take very Long. any other idea? – lolung Nov 17 '14 at 14:48