Java – multi row JTable unit with automatic height – very large first row
I am using swing to develop a java desktop application (JDK1.6) My question is about multiline cells (text wrapping) in JTable with the property of automatically adjusting cell height
I can already implement this structure in this way:
>Table has its own cellrenderer. > The cell is a jtextarea with wraptext = true > after inserting text into the cell, I calculate the row in the jtextarea and adjust the row height of the relevant row accordingly. > Cell width adjusts automatically (from preferred size)
Two questions about this structure:
1) During program execution, it can count rows and adjust the row height correctly
However, during the first initialization (the first setmodel ()), it calculates the number of rows in the "first cell" of the table, that is, (0,0), far exceeding it I debugged the code and found that it calculated the letters in the text and multiplied it by the line height of 16 (it seems that the width of the cell is 1 letter) Finally, I got a very high first row Any other line is OK
There is no problem when I do not insert any text into (0,0)
2) Row counting does not work when I disable the table auto size property and manually determine the cell width
This is my cell renderer:
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 deleted the line adjustment code outside the class This is represented by a model listener The first line is not very big at this time Calling this method is valid, but the problem is about calculating the line of the package Every time I fill a cell with very long text, the row is wrapped correctly, but my counter returns 1 (the code of the wrapper line counter is above. It is the same as that in the renderer. But it works normally there)
This is my model audience:
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 results:
Thanks in advance:)
ISIL
Solution
Just to get a solution immediately, even after a few years, it may help others You can set a fixed number of rows or use a dynamic row count appropriate to the content You should easily expand it in any way
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,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; } }