Многострочные ячейки JTable с автоматической высотой - очень большой первый ряд - PullRequest
4 голосов
/ 05 ноября 2011

Я разрабатываю Java-приложение для настольного компьютера (jdk1.6) с Swing. Моя проблема связана с многострочными ячейками (перенос текста) с автоматической настройкой свойства высоты ячейки в 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;

}

Вот как я вычисляю количество строк:

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. (код счетчика обернутой строки выше. Тот же, что и в рендерере. Но там он работал нормально)

вот мой модельный слушатель:

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();

}

Результат печати строк:

  • предпочитаемыйВысота: 15 // из функции обернутых строк
  • lineHeight: 15 // из функции обернутых строк
  • ч, нормальный: 25
  • numLines: 1
  • value: looooooooooooooooooooooonng tesssssssssssssssssssssssst // выглядит как 2 строки
  • ширина: 104

Заранее спасибо:)

Isil

1 Ответ

1 голос
/ 13 августа 2015

Просто для того, чтобы иметь решение под рукой прямо сейчас, даже через несколько лет, оно может помочь некоторым другим. Вы можете установить фиксированное количество строк или использовать динамический счетчик строк, который соответствует содержимому. Вам должно быть легко расширить это каким-либо образом.

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;
    }
}
...