Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set the RowHeight dynamically in a JTable

Tags:

java

swing

jtable

I want to put a String in a JTable that is longer than the given cell-width. How can I set the rowHeight dynamically so that I can read the whole String? Here is an example:

import javax.swing.*;

public class ExampleTable {

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", "dumdi dumdi dummdi dumm di di didumm"},
    {new Integer(10), "Sarah", "blabla bla bla blabla bla bla blabla"},};

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

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

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

    totalGUI.add(scrollPane);               
    return totalGUI;
}

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
}

And here you'll see the code which line-breaks each text that is to long for the given cell

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


    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 )  {
        setText( value.toString() );    
        return this;
      }
    }

thank you but I want to implement the RowHeight dynamically, depending on String length... I want to read the whole String/text in the cell. any suggestions?

I'm java beginner and this is my first question. I would be delighted I get an answer.

like image 687
Ramses Avatar asked Feb 12 '14 08:02

Ramses


People also ask

How do you make a JTable cell editable?

jTableAssignments = new javax. swing. JTable() { public boolean isCellEditable(int rowIndex, int colIndex) { return editable; }};

Can I add buttons in JTable?

We can add or insert a JButton to JTable cell by customizing the code either in DefaultTableModel or AbstractTableModel and we can also customize the code by implementing TableCellRenderer interface and need to override getTableCellRendererComponent() method.

How do you make a JTable column not editable?

Right-click on the table cells. From popup menu, choose "Table Contents..". Uncheck the editable check box for the column you want to make it non-editable.


2 Answers

There are several issues when using a JTextArea as rendering component (and most if not all of them already explained in several QA's on this site). Trying to sum them up:

Adjust individual row height to the size requirements of the rendering component

Basically, the way to go is to loop through the cells as needed, then

  • configure its renderer with the data
  • ask the rendering component for its preferred size
  • set the table row height to the pref height

The updateRowHeight method in the OP's edited question is just fine.

JTextArea's calculation of its preferredSize

to get a reasonable sizing hint for one dimension, it needs to be "seeded" with some reasonable size in the other dimension. That is if we want the height it needs a width, and that must be done in each call. In the context of a table, a reasonable width is the current column width:

public Component getTableCellRendererComponent(JTable table,
        Object value, boolean isSelected, boolean hasFocus, int row,
        int column) {
    ... // configure visuals
    setText((String) value);
    setSize(table.getColumnModel().getColumn(column).getWidth(),
            Short.MAX_VALUE);
    return this;
}// getTableCellRendererComponent

Dynamic adjustment of the height

The row height it fully determined in some steady state of the table/column/model. So you set it (call updateRowHeight) once after the initialization is completed and whenever any of the state it depends on is changed.

// TableModelListener
@Override
public void tableChanged(TableModelEvent e) {
    updateRowHeights();
}

// TableColumnModelListener
@Override
public void columnMarginChanged(ChangeEvent e) {
    updateRowHeights();
}

Note

As a general rule, all parameters in the getXXRendererComponent are strictly read-only, implementations must not change any state of the caller. Updating the rowHeight from within the renderer is wrong.

like image 66
kleopatra Avatar answered Oct 06 '22 02:10

kleopatra


I find it simplest to adjust the row height from inside the component renderer, like this:

public class RowHeightCellRenderer extends JTextArea implements TableCellRenderer
{
    public Component getTableCellRendererComponent(JTable table, Object 
            value, boolean isSelected, boolean hasFocus,
            int row, int column) {

        setText(value.toString());

        // Set the component width to match the width of its table cell
        // and make the height arbitrarily large to accomodate all the contents
        setSize(table.getColumnModel().getColumn(column).getWidth(), Short.MAX_VALUE);

        // Now get the fitted height for the given width
        int rowHeight = this.getPreferredSize().height;

        // Get the current table row height
        int actualRowHeight = table.getRowHeight(row);

        // Set table row height to fitted height.
        // Important to check if this has been done already
        // to prevent a never-ending loop.
        if (rowHeight != actualRowHeight) {
           table.setRowHeight(row, rowHeight);
        }

        return this;
    }
}

This will also work for a renderer which returns a JTextPane.

like image 22
Ned Howley Avatar answered Oct 06 '22 02:10

Ned Howley