3

I have a problem and really don't know how to solve it.
I used some solutions from this forum but they don't work.

This is the piece of code:

package own_components.custom_components;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.ListSelectionModel;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellRenderer;
import own_components.localizable_components.LocalizableComponent;
import localization.GUILocalizationTags;
import localization.LocalizationManager;

public class OutputJTable extends JTable implements CustomComponent
{
    private CustomTableModel dataModel = new CustomTableModel();
    private List<String[]> data = new ArrayList<String[]>();

    private final int COLUMNS_AMOUNT = 3;
    private final int _1ST_COL_WIDTH = 25;
    private final int _2ST_COL_WIDTH = 45;
    private final int _3ND_COL_WIDTH = 505;

    public OutputJTable()
    {
        setModel(dataModel);
        setTableProperties();
        dataModel.addTableModelListener(new TableModelListener(){

            @Override
            public void tableChanged(TableModelEvent paramTableModelEvent)
            {
                fitRowsHeight();

            }
        });
    }

    private void setTableProperties()
    {
        //some properties of table
    }

    public void setResultOutput(List<String[]> result)
    {
        data = new ArrayList<String[]>();
        data.add(new String[] { "l", "code", "222222222222222222222222222 22ddddddddddddddddddddddddddd22222222222222222222222222222222" });
        data.add(new String[] { "l", "code", "sssssssssssssssssssssssssssssss sssssssssssssssssssssssssssssssssssssssssssssssssss222222222" });
        dataModel.fireTableDataChanged();
    }

    private void fitRowsHeight()
    {
        for (int row = 0; row < getRowCount(); row++)
        {
            int rowHeight = getRowHeight();
            Component comp = prepareRenderer(getCellRenderer(row, 2), row, 2);
            rowHeight = Math.max(rowHeight, comp.getSize().height);
            setRowHeight(row, rowHeight);
        }
    }

    public int getSelectedRow()
    {
        return selectedRow;
    }

    private class CustomTableModel extends AbstractTableModel implements LocalizableComponent
    {

        private static final long serialVersionUID = -992340559233338699L;
        private String[] columnsNames = { "a", "b", "c" };

        @Override
        public String getColumnName(int paramInt)
        {
            return columnsNames[paramInt];
        }

        @Override
        public boolean isCellEditable(int paramInt1, int paramInt2)
        {
            return false;
        }

        @Override
        public int getColumnCount()
        {
            return COLUMNS_AMOUNT;
        }

        @Override
        public int getRowCount()
        {
            return data.size();
        }

        @Override
        public String getValueAt(int arg0, int arg1)
        {
            return data.get(arg0)[arg1];
        }

        @Override
        public void useTranslatedText(String tag)
        {
            columnsNames[1] = tag;
            getColumnModel().getColumn(2).setHeaderValue(tag);
            repaint();
        }

        @Override
        public void registerToLocalization(LocalizationManager lm, String key)
        {
            lm.registerToTranslationList(this, GUILocalizationTags.OUT_TAB_DESCRIPTION);
        }
    }

    private class CustomTableRenderer extends DefaultTableCellRenderer
    {
        JTextArea cellTemp = new JTextArea();
            @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
        {
            cellTemp = new JTextArea(data.get(row)[column]);
            cellTemp.setLineWrap(true);
            return cellTemp;
        }
    }
}

This is little bit long but rather simple: my table uses custom cell renderer which contains JTextArea. I use JTA because I need Strings wrapping. After put such JTextAreas I expect to set row heights to highest JTA in a row.

And here is the problem. In code above I expect to receive JTA.height but I still receive "0". The same situation with JTA.getRows().

I really don't understand why. Can anybody explain me what is wrong with this code?

rainbow
  • 979
  • 2
  • 11
  • 26
  • 1) For better help sooner, post an [SSCCE](http://sscce.org/). Note that an SSCCE can be a little longer than that and still be 'short', but it needs a `main(..)` & imports etc. 2) I'd look to use an HTML formatted label with a style specifying the maximum width. E.G. as seen in [this answer](http://stackoverflow.com/a/7861833/418556). 3) If using `JTextArea` I'd set the size by setting the columns, rows and font size, and combine that with word wrap & wrap style word (in a scroll pane). – Andrew Thompson Sep 27 '13 at 12:18
  • 2
    unrelated: don't re-create the textArea on each call, instead create it once and configure that instance in getXXCellRendererComponent as appropriate. The "trick" (afair needed because of some quirks to the area's internal prefSize calculation ) is to set the area's _width_ to the column width – kleopatra Sep 27 '13 at 12:49

1 Answers1

2

This is working JTable with wrapped strings.
(I used solutions introduced by mKorbel in this thread How to make a JTable column to contain not JTextFields, but JTextAreas)

package own_components.custom_components;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.util.ArrayList;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.ListSelectionModel;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.text.View;

public class OutputJTable extends JTable
{
    private static final long serialVersionUID = 1L;
private List<String[]> data = new ArrayList<String[]>();
private CustomTableModel dataModel = new CustomTableModel();

private final int COLUMNS_AMOUNT = 3;
private final int _1ST_COL_WIDTH = 25;
private final int _2ST_COL_WIDTH = 45;
private final int _3ND_COL_WIDTH = 505;

private int selectedRow = -1;


public OutputJTable()
{
    setModel(dataModel);
    setDefaultRenderer(Object.class, new CustomTableRenderer());
    setTableProperties();
}


/**
 * Sets basic table properties.
 */
private void setTableProperties()
{
    setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
    getColumnModel().getColumn(0).setMaxWidth(_1ST_COL_WIDTH);
    getColumnModel().getColumn(0).setMinWidth(_1ST_COL_WIDTH);
    getColumnModel().getColumn(1).setMaxWidth(_2ST_COL_WIDTH);
    getColumnModel().getColumn(1).setMinWidth(_2ST_COL_WIDTH);
    getColumnModel().getColumn(2).setMaxWidth(_3ND_COL_WIDTH);
    getColumnModel().getColumn(2).setMinWidth(_3ND_COL_WIDTH);
    setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    setIntercellSpacing(new Dimension(0, 0));
    setShowGrid(false);
}


/**
 * Receives data used to modified data showned in table.
 * This should be only access point to add data used by data model (which is used by jtable).
 * 
 * @param result
 */
public void setResultOutput(List<String[]> result)
{
    data = new ArrayList<String[]>();
    data = result;
    dataModel.fireTableDataChanged();
}


@Override
public void doLayout()
{
    super.doLayout();
    for (int row = 0; row < getRowCount(); row++)
    {
        JTextArea a = (JTextArea) prepareRenderer(getDefaultRenderer(Object.class), row, 2);
        int rowHeight = (int) a.getUI().getRootView(a).getView(0).getPreferredSpan(View.Y_AXIS) + getIntercellSpacing().height;
        setRowHeight(row, rowHeight);
    }
}


/**
 * Returns which row is selected. Main purpose of this method is provide data to PrintManager what should be printed.
 */
public int getSelectedRow()
{
    return selectedRow;
}


@Override
public void changeSelection(int rowIndex, int columnIndex, boolean toggle, boolean extend)
{
    if (rowIndex != selectedRow)
    {
        selectedRow = rowIndex;
    }
    else
    {
        selectedRow = -1;
    }
    super.changeSelection(rowIndex, columnIndex, true, false);
}


/**
 * This is model used to fill this table with data.
 */
private class CustomTableModel extends DefaultTableModel implements LocalizableComponent
{
    private static final long serialVersionUID = -992340559233338699L;
    private String[] columnsNames = { "a", "b", "c" };


    @Override
    public String getColumnName(int paramInt)
    {
        return columnsNames[paramInt];
    }


    @Override
    public boolean isCellEditable(int paramInt1, int paramInt2)
    {
        return false;
    }


    @Override
    public int getColumnCount()
    {
        return COLUMNS_AMOUNT;
    }


    @Override
    public int getRowCount()
    {
        return data.size();
    }


    @Override
    public String getValueAt(int arg0, int arg1)
    {
        return data.get(arg0)[arg1];
    }

}

/**
 * This class is used to render single cell.
 */
private class CustomTableRenderer extends JTextArea implements TableCellRenderer
{
    private final Color SELECTION_BORDER = new Color(200, 200, 200);
    private final Color ODD_BACKGR_COLOR = new Color(240, 240, 240);
    private final Color EVEN_BACKGR_COLOR = Color.WHITE;


    CustomTableRenderer()
    {
        setLineWrap(true);
        setWrapStyleWord(true);
        setEditable(false);
        setFont(getFont());
    }


    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
    {
        setText((String) value);

        setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
                    if (isSelected)
        {
            setBackground(SELECTION_BORDER);
        }
        else if (row % 2 != 0)
        {
            setBackground(ODD_BACKGR_COLOR);
        }
        else
        {
            setBackground(EVEN_BACKGR_COLOR);
        }
        return this;
    }
}
}

Remarks:

  • formating of row height is based on third column, if you want to take under consideration all columns, you have to use additional "for" loop in doLayout(),
  • 'dataModel' of this JTable is based on the List 'model',
  • setResultOutput() expect String[3]
    Thanks for everybodys help.
    Regards.
Abra
  • 11,631
  • 5
  • 25
  • 33
rainbow
  • 979
  • 2
  • 11
  • 26
  • btw there are a few attempts how to do it (and maybe correctly == not tried your code) – mKorbel Sep 27 '13 at 22:25
  • Please explain this part of your sentence in brackets. Yes there is other way in those thread but your doLayout() solution seems to be most clear. I didn't test performance (i see some glitches during formatting big table) but for my purpose this is enought. – rainbow Sep 27 '13 at 22:34
  • please tomorrow I'm from CET timezone, still I'd suggest to put JTextArea to JScrollPane and set maximum size, is very different to show 50-100 chars and 500chars, then cell will be huge, note then you would need to consume() mousescroll events from child JScrollPanes pleaced into JTable cells :-) – mKorbel Sep 27 '13 at 23:11
  • Indeed, it was quiet late. I am so confused with this table i didn't noticed :) In my case putting JTA in JSP can't be done. The whole table is in JScrollPane and this is exactly what i need even if cell is very big. – rainbow Sep 28 '13 at 08:29