Я разрабатываю настольное приложение Java (jdk1.6) с помощью Swing. Моя проблема связана с многострочными ячейками (обтекание текстом) с автоматической настройкой высоты ячейки в JTable.
Я уже мог реализовать эту структуру таким образом:
- Таблица имеет свой собственный рендерер ячеек.
- Ячейки 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();
}
Результат printlines:
- PreferredHeight: 15 // из функции обернутых строк
- lineHeight: 15 // из функции обернутых строк
- ч нормальный:25
- количество строк: 1
- value:looooooooooooooooooooooooonng tesssssssssssssssssssssssst // выглядит как 2 строки
- ширина: 104
Заранее спасибо :)
Исил