JTable variable height of cells and coloring Strings via HTML Tags

1.5k Views Asked by At

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.

1

There are 1 best solutions below

5
On

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