Search code examples
javaswingtablecellrenderer

JTable not honoring cell renderer's necessary height


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?


Solution

  • 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