Java 具有自动高度的多行JTable单元格-超大第一行

Java 具有自动高度的多行JTable单元格-超大第一行,java,swing,jtable,multiline,tablecellrenderer,Java,Swing,Jtable,Multiline,Tablecellrenderer,我正在用Swing开发一个Java桌面应用程序(jdk1.6)。我的问题是关于JTable中具有自动调整单元格高度属性的多行单元格(文本换行) 我已经可以通过以下方式实现此结构: 表有自己的cellrenderer 单元格为JTextArea,wraptext=true 在将文本插入单元格后,我计算JTextArea中的行数,并相应地调整相关行的行高 单元格宽度将自动调整。(来自首选尺寸) 关于这一结构的2个问题: 1) 在程序执行过程中,它可以正确地计算行数和调整行高 但在第一次初始化(f

我正在用Swing开发一个Java桌面应用程序(jdk1.6)。我的问题是关于JTable中具有自动调整单元格高度属性的多行单元格(文本换行)

我已经可以通过以下方式实现此结构:

  • 表有自己的cellrenderer
  • 单元格为JTextArea,wraptext=true
  • 在将文本插入单元格后,我计算JTextArea中的行数,并相应地调整相关行的行高
  • 单元格宽度将自动调整。(来自首选尺寸)
关于这一结构的2个问题:

1) 在程序执行过程中,它可以正确地计算行数和调整行高

但在第一次初始化(first 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;
------------------------------------ 我将行调整代码移到了类的外部。该表现在有一个模型侦听器。第一排在这个时候不是很大。调用此方法是可行的,但问题是如何计算包裹的行。每次我用很长的文本填充单元格时,行被正确包装,但我的计数器返回1。(代码wrappedline计数器在上面。与渲染器中的计数器相同。但在那里工作正常)

以下是我的模型侦听器:

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();
公共类ModelListener实现TableModelListener{
JTable主表;
JTable-depTable;
公共模型侦听器(JTable m,JTable d){
主表=m;
depTable=d;
}
公共模型侦听器(JTM表){
主表=m;
depTable=null;
}
公共作废表已更改(TableModelEvent tme){
int fRow=tme.getFirstRow();
int col=tme.getColumn();
JTextArea=(JTextArea)mainTable.getDefaultRenderer(Object.class);
int numOfLines=getWrappedLines(cerellea);//countLines();
int height_normal=mainTable.getRowHeight(fRow);
System.out.println(“h正常:+高度正常”);
System.out.println(“numLines:+numOfLines”);
System.out.println(“值:”+mainTable.getModel().getValueAt(fRow,col));
System.out.println(“宽度:+ceralea.getPreferredSize().width”);
if(depTable==null)
{
如果(高度_正常值
}

打印行的结果:

  • preferredHeight:15//来自换行函数
  • 线宽:15//from wrapped lines函数
  • h正常值:25
  • 数字:1
  • 值:loooooooooooooooooooooong tesssssssssssssssst//似乎是两行
  • 宽度:104
提前感谢:)


Isil

现在就有解决方案在手,即使几年后,它可能会帮助其他一些人。您可以设置固定的行数或使用适合内容的动态行数。您可以以任何方式扩展它

package.com.mycompany;
导入java.awt.Component;
导入java.util.List;
导入javax.swing.JTable;
导入javax.swing.JTextArea;
导入javax.swing.border.EmptyBorder;
导入javax.swing.table.TableCellRenderer;
公共类MultilecellRenderer扩展了JTextArea实现
TableCell渲染器{
私有静态最终长serialVersionUID=1L;
布尔极限=假;
公共多容器渲染器(){
setLineWrap(真);
setWrapStyleWord(true);
set不透明(true);
新订单(新的空订单(-1,2,-1,2));
此.limit=false;
设置行(1);
}
公共多行渲染器(int行){
这个();
设置行(行);
this.limit=true;
}
@凌驾
公共组件GetTableCellRenderComponent(JTable表、对象值、,
布尔值(已选择,布尔值为焦点,整数行,整数列){
setText(value==null?“:value.toString());
int dynamicHeight=getLineCount()>getRows()&&this.limit?getRows():getLineCount();
int newHeight=table.getRowHeight()*动态灯光;
if(table.getRowHeight(row)!=newHeight){
表.setRowHeight(行,新高度);
}
如果(当选){
setForeground(table.getSelectionForeground());
挫折背景(table.getSelectionBackground());
}
否则{
set前台(table.get前台());
挫折背景(table.getBackground());
}
归还这个;
}
}

没有调查你的问题,只是:不要(就像“从来没有”一样)从渲染器内部更改表的状态。相反,将大小调整逻辑移到其他位置:循环表的行,使用值准备渲染器,查询其首选大小/换行线,并根据设置行高JTextArea是否认为它只有一行高,而不设置J的宽度TextArea,您将永远无法确定它应该有多高。但是宽度是自动设置的,并且这个问题只发生在相关表的(0,0)索引中,尽管所有单元格都派生自具有相同属性的相同类。我还记得将单元格宽度设置为固定值(很抱歉,该项目不再开发)没有任何帮助。@kleopatra您介意解释一下原因吗?@isilpekel我一直在测试您的代码,当您遵循时问题就消失了
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();