3

This should be simple, but I can't figure out what is going wrong. I need my table to display with a fairly large font size but the table painter is not honoring the height of the cell renderer.

I've seen this post and it's working brilliantly for when my preferences window has been given a changed font size. But although the renderer knows what font size to use, the table on initial display is using the standard row height (16). Surely the table painter should automatically take into account the preferred height of the renderer? Or do I actually have to manually tell it what height to use?

I've tried a call to doLayout() as shown below, but it doesn't make any difference.

Here's an SSCCE to demonstrate the problem:

public class IncorrectRowHeight extends JPanel
{
    private class MyCellRenderer extends JTextField implements TableCellRenderer
    {
        private MyCellRenderer()
        {
            setFont(new Font("SansSerif", Font.PLAIN, 30));
            setBorder(BorderFactory.createEmptyBorder());
        }

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
                                                       int row, int column)
        {
            setText(value.toString());
            return this;
        }
    }

    public IncorrectRowHeight()
    {
        super(new BorderLayout());

        add(new JTextField(25), BorderLayout.PAGE_START);

        String[][] data = {
                {"a", "b", "c", "d", "e"},
                {"f", "g", "h", "i", "j"},
                {"k", "l", "m", "n", "o"},
                {"p", "q", "r", "s", "t"}
        };
        String[] cols = {"h1", "h2", "h3", "h4", "h5"};
        JTable t = new JTable(data, cols);
        t.setGridColor(Color.GRAY);
        t.setPreferredScrollableViewportSize(new Dimension(300, 65));
        TableColumnModel model = t.getColumnModel();
        for (int i = 0; i < model.getColumnCount(); i++)
        {
            TableColumn column = model.getColumn(i);
            column.setCellRenderer(new MyCellRenderer());
        }
        JScrollPane scroller = new JScrollPane(t);
        add(scroller, BorderLayout.CENTER);

        //t.doLayout();  // doesn't help matters
    }

    private static void createAndShowGUI()
    {
        JFrame frame = new JFrame("IncorrectRowHeight");
        JComponent newContentPane = new IncorrectRowHeight();
        newContentPane.setOpaque(true);
        frame.setContentPane(newContentPane);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args)
    {
        javax.swing.SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowGUI();
            }
        });
    }
}

It produces the following:

This ain't rocket science! What am I doing wrong?

skiaddict1
  • 523
  • 7
  • 19
  • The `JTable` uses the `rowHeight` property to determine the height of the rows. You might consider using it to try and estimate the best height for the rows – MadProgrammer Dec 15 '17 at 08:20
  • So, in other words I need to tell JTable what height to use, there's no way it's going to be intelligent enough to figure it out from the cell renderers??? – skiaddict1 Dec 15 '17 at 09:28

2 Answers2

2

Probably this method help you

public static void updateRowHeight(JTable table, int margin) {
    final int rowCount = table.getRowCount();
    final int colCount = table.getColumnCount();
    for (int i = 0; i < rowCount; i++) {
        int maxHeight = 0;
        for (int j = 0; j < colCount; j++) {
            final TableCellRenderer renderer = table.getCellRenderer(i, j);
            maxHeight = Math.max(maxHeight, table.prepareRenderer(renderer, i, j).getPreferredSize().height);
        }
        table.setRowHeight(i, maxHeight + margin);
    }
}

Use this method after the table is populated with the data. margin parameter is used for additional increment of row height. If not required - use 0.

Here is your example with the correct cell height.

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;

import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;

/**
 * <code>IncorrectRowHeight</code>.
 */
public class IncorrectRowHeight extends JPanel {
    private class MyCellRenderer extends JTextField implements TableCellRenderer {
        private MyCellRenderer() {
            setFont(new Font("SansSerif", Font.PLAIN, 30));
            setBorder(BorderFactory.createEmptyBorder());
        }

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row,
                int column) {
            setText(value.toString());
            return this;
        }
    }

    public IncorrectRowHeight() {
        super(new BorderLayout());

        add(new JTextField(25), BorderLayout.PAGE_START);

        String[][] data = {{"a", "b", "c", "d", "e"}, {"f", "g", "h", "i", "j"}, {"k", "l", "m", "n", "o"}, {"p", "q", "r", "s", "t"}};
        String[] cols = {"h1", "h2", "h3", "h4", "h5"};
        JTable t = new JTable(data, cols);
        t.setGridColor(Color.GRAY);
        t.setPreferredScrollableViewportSize(new Dimension(300, 65));
        TableColumnModel model = t.getColumnModel();
        for (int i = 0; i < model.getColumnCount(); i++) {
            TableColumn column = model.getColumn(i);
            column.setCellRenderer(new MyCellRenderer());
        }
        updateRowHeight(t, 0);
        JScrollPane scroller = new JScrollPane(t);
        add(scroller, BorderLayout.CENTER);
    }

    public static void updateRowHeight(JTable table, int margin) {
        final int rowCount = table.getRowCount();
        final int colCount = table.getColumnCount();
        for (int i = 0; i < rowCount; i++) {
            int maxHeight = 0;
            for (int j = 0; j < colCount; j++) {
                final TableCellRenderer renderer = table.getCellRenderer(i, j);
                maxHeight = Math.max(maxHeight, table.prepareRenderer(renderer, i, j).getPreferredSize().height);
            }
            table.setRowHeight(i, maxHeight + margin);
        }
    }

    private static void createAndShowGUI() {
        JFrame frame = new JFrame("IncorrectRowHeight");
        JComponent newContentPane = new IncorrectRowHeight();
        newContentPane.setOpaque(true);
        frame.setContentPane(newContentPane);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                createAndShowGUI();
            }
        });
    }
}
Sergiy Medvynskyy
  • 11,160
  • 1
  • 32
  • 48
  • Thanks, this would be good for the case where different rows need to be of different heights. In my case that's not necessary. – skiaddict1 Dec 16 '17 at 02:46
0

Use table.setRowHeight(table.getFontMetrics(font).getHeight());

package com.logicbig.example;

import javax.swing.*;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import java.awt.*;

public class IncorrectRowHeight extends JPanel {
private static final Font font = new Font("SansSerif", Font.PLAIN, 30);
private class MyCellRenderer extends JTextField implements TableCellRenderer {
    private MyCellRenderer() {
        setFont(font);
        setBorder(BorderFactory.createEmptyBorder());
    }

    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
                                                   int row, int column) {
        setText(value.toString());
        return this;
    }
}

public IncorrectRowHeight() {
    super(new BorderLayout());

    add(new JTextField(25), BorderLayout.PAGE_START);

    String[][] data = {
            {"a", "b", "c", "d", "e"},
            {"f", "g", "h", "i", "j"},
            {"k", "l", "m", "n", "o"},
            {"p", "q", "r", "s", "t"}
    };
    String[] cols = {"h1", "h2", "h3", "h4", "h5"};
    JTable t = new JTable(data, cols);
    t.setRowHeight(t.getFontMetrics(font).getHeight());
    t.setGridColor(Color.GRAY);
    t.setPreferredScrollableViewportSize(new Dimension(300, 65));
    TableColumnModel model = t.getColumnModel();
    for (int i = 0; i < model.getColumnCount(); i++) {
        TableColumn column = model.getColumn(i);
        column.setCellRenderer(new MyCellRenderer());
    }
    JScrollPane scroller = new JScrollPane(t);
    add(scroller, BorderLayout.CENTER);

    //t.doLayout();  // doesn't help matters
}

private static void createAndShowGUI() {
    JFrame frame = new JFrame("IncorrectRowHeight");
    JComponent newContentPane = new IncorrectRowHeight();
    newContentPane.setOpaque(true);
    frame.setContentPane(newContentPane);
    frame.pack();
    frame.setVisible(true);
}

public static void main(String[] args) {
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            createAndShowGUI();
        }
    });
  }
 }

enter image description here

Joe
  • 140
  • 1
  • 1
  • 9