Multi-Linear Auto-Height JTable Cells - Very Big First Row

I am developing a Java Desktop application (jdk1.6) with Swing. My problem is with multi-line cells (text wrapping) with automatically setting the cell height property in JTable.

I could already implement this structure as follows:

  • The table has its own cellrenderer.
  • JTextArea cells with wraptext = true
  • I count the lines in JTextArea after pasting the text into the cell and adjusts the line height of the corresponding line accordingly.
  • The cell width is automatically adjusted. (of preferred size)

2 problems about this structure:

1) While the program is running, it can count the lines and correctly adjust the line height.

But at the first initialization (first setModel ()), it calculates the row counter of the "first cell" of the table, that is (0,0), much more than it is. I debugged the code and found that it counts the letters in the text and is multiplied by the height of line 16. (as if the cell width is 1 letter). In the end, I get a very high front row. Other lines are fine.

When I do not paste the text in (0,0), there are no problems.

2) The number of rows does not work when I turn off the automatic table modification property and manually determine the cell width.

Here is my cell rendering:

public class MultiLineCellRenderer extends JTextArea implements TableCellRenderer { private JTable DependentTable; public MultiLineCellRenderer() { DependentTable=null; setLineWrap(true); setWrapStyleWord(true); setOpaque(true); } public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { (...) //some background color adjustments setText((value == null) ? "" : value.toString()); int numOfLines = getWrappedLines(this); // Counting the lines int height_normal = table.getRowHeight(row);// read the height of the row if(DependentTable == null) // for this case always null { if (height_normal < numOfLines*16) { table.setRowHeight(row,numOfLines*16); } } else (...) return this; 

}

This is how I calculate the number of rows:

 public static int getWrappedLines(JTextArea component) { View view = component.getUI().getRootView(component).getView(0); int preferredHeight = (int)view.getPreferredSpan(View.Y_AXIS); int lineHeight = component.getFontMetrics( component.getFont() ).getHeight(); return preferredHeight / lineHeight; } 

------------------------------------

I removed the line-correction code outside the class. The table now has a model receiver. This time the first line is not extremely large. Calling this method works, but the problem is counting the wrapped lines. Every time I fill a cell with very long text, the line wraps properly, but my counter returns 1. (the wrapper line counter code is above. Same as in the renderer. But it worked fine there)

here is my model listener:

 public class ModelListener implements TableModelListener { JTable mainTable; JTable depTable; public ModelListener(JTable m, JTable d) { mainTable = m; depTable = d; } public ModelListener(JTable m){ mainTable = m; depTable = null; } public void tableChanged(TableModelEvent tme) { int fRow = tme.getFirstRow(); int col = tme.getColumn(); JTextArea cellArea = (JTextArea)mainTable.getDefaultRenderer(Object.class); int numOfLines = getWrappedLines(cellArea); //countLines(); int height_normal = mainTable.getRowHeight(fRow); System.out.println("h normal:"+height_normal); System.out.println("numLines:"+numOfLines); System.out.println("value:"+mainTable.getModel().getValueAt(fRow, col)); System.out.println("width:"+cellArea.getPreferredSize().width); if(depTable == null) { if (height_normal < numOfLines*16) { mainTable.setRowHeight(fRow,numOfLines*16); } } else { //(---) } mainTable.repaint(); 

}

Print result:

  • preferredHeight: 15 // from the wrapped string function
  • lineHeight: 15 // from the wrapped string function
  • h normal: 25
  • numLines: 1
  • Value: looooooooooooooooooooooooonng tesssssssssssssssssssssssssstst // displayed as 2 lines
  • width: 104

Thank you in advance:)

Isil

+4
source share
1 answer

Just to have a solution on hand right now, even after a few years, it may help some others. you can set a fixed number of lines or use the dynamic line Count, which corresponds to the Content. It should be easy for you to expand this.

 package com.mycompany; import java.awt.Component; import java.util.List; import javax.swing.JTable; import javax.swing.JTextArea; import javax.swing.border.EmptyBorder; import javax.swing.table.TableCellRenderer; public class MultiLineCellRenderer extends JTextArea implements TableCellRenderer { private static final long serialVersionUID = 1L; boolean limit = false; public MultiLineCellRenderer() { setLineWrap(true); setWrapStyleWord(true); setOpaque(true); setBorder(new EmptyBorder(-1, 2, -1, 2)); this.limit = false; setRows(1); } public MultiLineCellRenderer(int rows) { this(); setRows(rows); this.limit = true; } @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { setText(value == null ? "" : value.toString()); int dynamicHeight = getLineCount() > getRows() && this.limit ? getRows() : getLineCount(); int newHeight = table.getRowHeight() * dynamicHeight; if (table.getRowHeight(row) != newHeight) { table.setRowHeight(row, newHeight); } if (isSelected) { setForeground(table.getSelectionForeground()); setBackground(table.getSelectionBackground()); } else { setForeground(table.getForeground()); setBackground(table.getBackground()); } return this; } } 
+1
source

Source: https://habr.com/ru/post/1379785/


All Articles