4

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

我已经可以通过这种方式实现这个结构:

  • 表有自己的单元格渲染器。
  • 单元格是 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;
} 

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

我将行调整代码删除到课堂之外。该表现在有一个模型侦听器。这次第一行不是特别大。调用此方法有效,但问题在于计算换行的行数。每次我用很长的文本填充单元格时,该行都会正确换行,但我的计数器返回 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();

}

打印线的结果:

  • preferredHeight: 15 // 来自换行函数
  • lineHeight: 15 // 来自换行函数
  • 小时正常:25
  • 行数:1
  • value:looooooooooooooooooooooonng tessssssssssssssssssssssst // 看起来是 2 行
  • 宽度:104

提前致谢 :)

伊西尔

4

1 回答 1

2

只是因为现在手头有解决方案,即使在几年后,它也可能对其他人有所帮助。您可以设置固定数量的行或使用适合内容的动态行计数。您应该很容易以任何方式扩展它。

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;
    }
}
于 2015-08-13T12:53:46.300 回答