Question

I have a JScrollPane that's displaying a JTable, and the JTable has varying row heights based on how many lines are needed to fit the text in each cell, as defined by this custom

DefaultTableCellRenderer renderer = new DefaultTableCellRenderer() {

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

            Component rendererComp = super.getTableCellRendererComponent(table, obj, isSelected, hasFocus,
                    row, column);
            if(column == 5) {
                JTextArea text = new JTextArea(obj.toString());
                text.setFont(rendererComp.getFont());
                text.setLineWrap(true);
                text.setWrapStyleWord(true);
                text.setSize(new Dimension(
                        moves.getColumnModel().getColumn(column).getWidth(),
                        9999999));
                text.setSize(text.getSize().width, text.getPreferredSize().height);
                table.setRowHeight(row, text.getPreferredSize().height);
                return text;
            } else 
                return rendererComp;
        }
    };

Only column five gets a text area because only column five can have enough text to require multiple lines.

The reason I included this is that the JScrollPane was working fine before I added this renderer, but this needs to be the cell renderer because otherwise some of the information in the JTable simply isn't displayed. And it works fine for creating the rows at the correct heights. However, the JTable's preferredSize is apparently calculating incorrectly (I'm sure it's not and I messed something up but that's what it seems like), as now the JScrollPane doesn't scroll all the way to the bottom. And when I called getRowHeight on every row in the JTable after setting the cell renderer for each column, they all return 16, despite there very clearly being rows with different heights in the JTable. Here's what the table looks like at the moment:

enter image description here

As you can see, there's a sliver of the next row that should be displayed, but can't be because the scrollbar doesn't actually scroll all the way down the table. I've already set the preferred size of both the JTable and JScrollPane, and I've even gotten the whole table to display by adding arbitrary constants to the height of the JTable's preferred size, but the program needs to be able to calculate the correct size based on the information in the table. I'd just like to know how to accurately display the whole JTable in the JScrollPane. If seeing any other parts of the code could help just let me know, and sorry for not posting it to begin with.

Was it helpful?

Solution

I have no problems with the renderer posted. You can check my code at the bottom. All I can suggest is

  • Don't set sizes to anything. Learn to use Layout Managers and just pack your frame so all preferred sizes are respected.

  • Even in your renderer, don't set the size of the JTextArea instead use this contructor

    JTexArea(String text, int rows, int columns)
    
  • Don't use null layouts. I've seen a similar problem with someone trying to set bounds on the table.


import java.awt.Component;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableCellRenderer;

public class Test {

    public Test() {
        String[][] data = {
            {"sdvjdnvdfjvnsdvsdjvs", "sdvjdnvdfjvnsdvsdjvsdvkdsjvnbdvlkjvnbdkvdvkdjvvsnvlkdnv"},
            {"sdvjdnvdfjvnsdvsdjvs", "sdvjdnvdfjvnsdvsdjvsdvkdsjvnbdvlkjvnbdkvdvkdjvvsnvlkdnv"},
            {"sdvjdnvdfjvnsdvsdjvs", "sdvjdnvdfjvnsdvsdjvsdvkdsjvnbdvlkjvnbdkvdvkdjvvsnvlkdnv"},
            {"sdvjdnvdfjvnsdvsdjvs", "sdvjdnvdfjvnsdvsdjvsdvkdsjvnbdvlkjvnbdkvdvkdjvvsnvlkdnv"},
            {"sdvjdnvdfjvnsdvsdjvs", "sdvjdnvdfjvnsdvsdjvsdvkdsjvnbdvlkjvnbdkvdvkdjvvsnvlkdnv"},
            {"sdvjdnvdfjvnsdvsdjvs", "sdvjdnvdfjvnsdvsdjvsdvkdsjvnbdvlkjvnbdkvdvkdjvvsnvlkdnv"},
            {"sdvjdnvdfjvnsdvsdjvs", "sdvjdnvdfjvnsdvsdjvsdvkdsjvnbdvlkjvnbdkvdvkdjvvsnvlkdnv"},
            {"sdvjdnvdfjvnsdvsdjvs", "sdvjdnvdfjvnsdvsdjvsdvkdsjvnbdvlkjvnbdkvdvkdjvvsnvlkdnv"},
            {"sdvjdnvdfjvnsdvsdjvs", "sdvjdnvdfjvnsdvsdjvsdvkdsjvnbdvlkjvnbdkvdvkdjvvsnvlkdnv"},
            {"sdvjdnvdfjvnsdvsdjvs", "sdvjdnvdfjvnsdvsdjvsdvkdsjvnbdvlkjvnbdkvdvkdjvvsnvlkdnv"},
            {"sdvjdnvdfjvnsdvsdjvs", "sdvjdnvdfjvnsdvsdjvsdvkdsjvnbdvlkjvnbdkvdvkdjvvsnvlkdnv"},
            {"sdvjdnvdfjvnsdvsdjvs", "sdvjdnvdfjvnsdvsdjvsdvkdsjvnbdvlkjvnbdkvdvkdjvvsnvlkdnv"},
            {"sdvjdnvdfjvnsdvsdjvs", "sdvjdnvdfjvnsdvsdjvsdvkdsjvnbdvlkjvnbdkvdvkdjvvsnvlkdnv"},
            {"sdvjdnvdfjvnsdvsdjvs", "sdvjdnvdfjvnsdvsdjvsdvkdsjvnbdvlkjvnbdkvdvkdjvvsnvlkdnv"},
            {"sdvjdnvdfjvnsdvsdjvs", "sdvjdnvdfjvnsdvsdjvsdvkdsjvnbdvlkjvnbdkvdvkdjvvsnvlkdnv"},
            {"sdvjdnvdfjvnsdvsdjvs", "sdvjdnvdfjvnsdvsdjvsdvkdsjvnbdvlkjvnbdkvdvkdjvvsnvlkdnv"},
            {"sdvjdnvdfjvnsdvsdjvs", "sdvjdnvdfjvnsdvsdjvsdvkdsjvnbdvlkjvnbdkvdvkdjvvsnvlkdnv"},
            {"sdvjdnvdfjvnsdvsdjvs", "sdvjdnvdfjvnsdvsdjvsdvkdsjvnbdvlkjvnbdkvdvkdjvvsnvlkdnv"},
            {"sdvjdnvdfjvnsdvsdjvs", "sdvjdnvdfjvnsdvsdjvsdvkdsjvnbdvlkjvnbdkvdvkdjvvsnvlkdnv"},
            {"sdvjdnvdfjvnsdvsdjvs", "sdvjdnvdfjvnsdvsdjvsdvkdsjvnbdvlkjvnbdkvdvkdjvvsnvlkdnv"},
            {"sdvjdnvdfjvnsdvsdjvs", "sdvjdnvdfjvnsdvsdjvsdvkdsjvnbdvlkjvnbdkvdvkdjvvsnvlkdnv"}};

        String[] cols = {"COL 1", "COL 2"};

        final JTable moves = new JTable(data, cols);

        DefaultTableCellRenderer renderer = new DefaultTableCellRenderer() {

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

                Component rendererComp = super.getTableCellRendererComponent(table, obj, isSelected, hasFocus,
                        row, column);
                if (column == 1) {
                    JTextArea text = new JTextArea(obj.toString(), 2, 20);
                    text.setFont(rendererComp.getFont());
                    text.setLineWrap(true);
                    text.setWrapStyleWord(true);
                    text.setSize(text.getSize().width, text.getPreferredSize().height);
                    table.setRowHeight(row, text.getPreferredSize().height);
                    return text;
                } else {
                    return rendererComp;
                }
            }
        };

        moves.setDefaultRenderer(Object.class, renderer);

        JFrame frame = new JFrame();
        frame.add(new JScrollPane(moves));
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                Test test = new Test();
            }
        });
    }
}

OTHER TIPS

I solved this by iterating over each row and summing the row height, and then set the table preferred size to the total height.

public final void updateTablePreferredSize ( JTable table )
{
    int totalRowHeight = 0;

    for ( int row = 0; row < table.getRowCount(); row++ )
    {
        totalRowHeight +=  table.getRowHeight(row);
    }

    Dimension dimension = table.getPreferredSize();
    dimension.setSize ( dimension.getWidth(), totalRowHeight );
    table.setPreferredSize(dimension);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top