2

i've implemented updateRowHeights, method to auto adjust the height of rows in Jtable, but it doesn't work although my code works fine so far. Did I got forgot anything? (see: Auto adjust the height of rows in a JTable)

here is my code:

import javax.swing.*;
import java.awt.*;

public class ExampleTable {
JTable textTable;

public JPanel createTable() {               
    JPanel totalGUI = new JPanel();

    //define titles for table
    String[] title = {"TITLE1", "TITLE2", "TITLE3"};

    //table data
    Object[][] playerdata = {       
    {new Integer(34), "Steve", "test test test"},
    {new Integer(32), "Patrick", "du hu hu hu hu hu hu hu uh u kkkkkk oooo pppp"},
    {new Integer(10), "Sarah", "xxxxxxxxxxxxx aaaaaaaaaa bbbbbbbbbbbbb dddddddddddd xxxxxxx gggewr  eeeeeeeeee ddd g fffffff zzzzzzz"},};

    //create object 'textTable'
    textTable = new JTable(playerdata,title);

    //set column width
    textTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); 
    textTable.getColumnModel().getColumn(0).setPreferredWidth(45);
    textTable.getColumnModel().getColumn(1).setPreferredWidth(45);
    textTable.getColumnModel().getColumn(2).setPreferredWidth(200);
    textTable.setDefaultRenderer(String.class, new RowHeightCellRenderer());

    //adjust dynamically the Row height of each cell
    updateRowHeights();

    //put line breaks if string is longer than cell-width
    RowHeightCellRenderer dynRow = new RowHeightCellRenderer();
    textTable.getColumnModel().getColumn(2).setCellRenderer(dynRow);
    System.out.println(textTable.getPreferredSize().height);

    //scrollbar
    JScrollPane scrollPane = new JScrollPane(textTable);

    totalGUI.add(scrollPane);               
    return totalGUI;
}

private void updateRowHeights() {

    /* 
     * Auto adjust the height of rows in a JTable.
     * The only way to know the row height for sure is to render each cell 
     * to determine the rendered height. After your table is populated with 
     * data you can do:         
     *  
     */        
    for (int row = 0; row < textTable.getRowCount(); row++) {
        int rowHeight = textTable.getRowHeight();
        for (int column = 0; column < textTable.getColumnCount(); column++)
        {
            Component comp = textTable.prepareRenderer(textTable.getCellRenderer(row, column), row, column);
            System.out.println("Row: "+row+" Column: "+column+ " preferredHeight: "+comp.getPreferredSize().height);
            rowHeight = Math.max(rowHeight, comp.getPreferredSize().height);
            System.out.println("Row: "+row+" Column: "+column+ " RowHeight: "+rowHeight);
        }
        textTable.setRowHeight(row, rowHeight);
    }
}

private static void createAndShowGUI() {

    //create main frame
    JFrame mainFrame = new JFrame("");
    ExampleTable test = new ExampleTable();
    JPanel totalGUI = new JPanel();
    totalGUI = test.createTable();

    //visible mode
    mainFrame.add(totalGUI); //integrate main panel to main frame
    mainFrame.pack();
    mainFrame.setVisible(true);     
}


public static void main (String[] args) {               

    createAndShowGUI();     

}//main
}

import java.awt.*;
    import javax.swing.*;
    import javax.swing.table.*;

And here is RowHeightCellRenderer:

    public class RowHeightCellRenderer extends JTextArea implements TableCellRenderer
    {
      /**
         * 
         */
        private static final long serialVersionUID = 1L;

    public Component getTableCellRendererComponent (JTable table, 
                                                    Object value, 
                                                    boolean isSelected, 
                                                    boolean hasFocus, 
                                                    int row, 
                                                    int column )  {
          this.setText((String)value);
          this.setLineWrap(true); //line break if String longer than the cell width
        return this;
      }
    }

Many thanks in advance!!

Community
  • 1
  • 1
Ramses
  • 652
  • 2
  • 8
  • 30
  • search here for JTable + doLayout(), thats simpler – mKorbel Feb 12 '14 at 20:57
  • I changed the order as mentioned by Holger but it still doesn't have any effect, and I know why: the renderer always gets 18 as preferredHeight in updateRowHeight although it definetly has to be higher, but why?? – Ramses Feb 13 '14 at 10:47
  • Did you notice the update of my answer? I would like to know whether it worked for you… – Holger Mar 05 '14 at 10:22

1 Answers1

3

Look at your code:

updateRowHeights();

//put line breaks if string is longer than cell-width
RowHeightCellRenderer dynRow = new RowHeightCellRenderer();
textTable.getColumnModel().getColumn(2).setCellRenderer(dynRow);

You update the row heights and set the cell renderer afterwards. So the update method obviously can’t use the intended cell renderer. Change the order:

//put line breaks if string is longer than cell-width
RowHeightCellRenderer dynRow = new RowHeightCellRenderer();
textTable.getColumnModel().getColumn(2).setCellRenderer(dynRow);

updateRowHeights();

You have to ensure that all properties which affect the visual appearance of the cells are setup before calculating and applying the derived cell height.


Another problem is that the AWT layout concept, i.e. getPreferredSize(), does not play very well with the concept of word-wrapping where you need to query for “preferred height under a given actual width”. You have to interact with the Swing text API to do such a query:

private void updateRowHeights() {
    final TableColumnModel columnModel = textTable.getColumnModel();
    Insets i=null;
    for(int row = 0; row < textTable.getRowCount(); row++) {
        int rowHeight = textTable.getRowHeight();
        for(int column = 0; column < textTable.getColumnCount(); column++) {
            Component comp = textTable.prepareRenderer(
                textTable.getCellRenderer(row, column), row, column);
            final int height;
            if(comp instanceof JTextComponent) {
                final JTextComponent tc = (JTextComponent)comp;
                final View rootView = tc.getUI().getRootView(tc);
                i=tc.getInsets(null);
                rootView.setSize(columnModel.getColumn(column)
                    .getPreferredWidth()-i.left-i.right,
                    Integer.MAX_VALUE);
                height=(int)rootView.getPreferredSpan(View.Y_AXIS);
            }
            else height = comp.getPreferredSize().height;
            rowHeight = Math.max(rowHeight, height);
        }
        textTable.setRowHeight(row, rowHeight);
    }
}
Holger
  • 285,553
  • 42
  • 434
  • 765
  • thank you for your advise. I changed the order as mentioned but it still doesn't have any effect, and I know why: the renderer always gets 18 as preferredHeight in updateRowHeight although it definetly has to be higher, but why?? – Ramses Feb 13 '14 at 08:48
  • @user3300710: then you have to show your cell renderer’s code. – Holger Feb 13 '14 at 08:56
  • search here Swing + JTable + JTextArea (in posts by @aterai) or in my post Swing + JTable + JTextArea + doLayout() – mKorbel Feb 13 '14 at 12:55
  • Added solution to the secondary problem. – Holger Feb 13 '14 at 17:16