我正在使用Swing开发Java桌面应用程序(jdk1.6).我的问题是关于JTable中具有自动调整单元格高度属性的多行单元格(文本换行).
我已经可以用这种方式实现这个结构了:
> Table有自己的cellrenderer.
>单元格是带有wraptext = true的JTextArea
>我在将文本插入单元格后计算JTextArea中的行,并相应地调整相关行的行高.
>单元格宽度自动调整. (从首选尺寸)
关于这种结构的2个问题:
1)在程序执行期间,它可以对行进行计数并正确调整行高.
但是在第一次初始化时(第一个setModel()),它计算表的“第一个单元”的行数,即(0,0),远远超过它.我调试了代码并发现它计算文本中的字母并乘以行高16.(好像单元格的宽度是1个字母).最后,我获得了非常高的第一排.其他行都可以.
当我没有向(0,0)插入任何文本时,不会出现问题.
2)当我禁用表自动调整大小属性并手动确定单元格宽度时,行计数不起作用.
这是我的单元格渲染器:
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;
}
这是我如何计算行数:
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;
}
————————————
我将行调整代码删除到了类的外部.该表现在有一个Model Listener.第一行在这个时候并不是非常大.调用此方法有效但问题是关于计算包裹的行.每次我用非常长的文本填充单元格时,行都被正确包装但我的计数器返回1.(包装线计数器的代码在上面.与渲染器中的相同.但它在那里工作正常)
这是我的模特听众:
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();
}
印刷品的结果:
- preferredHeight: 15 // from wrapped lines function
- lineHeight: 15 // from wrapped lines function
- h normal:25
- numLines:1
- value:looooooooooooooooooooooonng tesssssssssssssssssssssssst // appears to be 2 lines
- width:104
提前致谢 :)
ISIL
解决方法:
只是为了立即获得解决方案,即使在几年后,它可能会帮助其他人.您可以设置固定数量的行或使用适合内容的动态行计数.你应该很容易以任何方式扩展它.
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;
}
}