2012-01-23 5 views
2

У меня есть редактируемый JTable. Поскольку пользователь вводит, если текст длиннее ширины, мне нужна высота для роста. Я установил linewrap в true, но это только изменяет высоту после нажатия пользователем ввода. Что мне не хватает? Я посмотрел на ответы, которые решают проблему изменения размера (например, this в CellRenderer, но мне нужно, чтобы отрегулировать высоту, как типы пользователей, а не после того, как они закончили печатать.Как изменить размер строки JTable как пользовательский тип?

public class EndCycleCellEditor extends AbstractCellEditor implements TableCellEditor, KeyListener { 
    JComponent component; 

    private ArrayList<ArrayList<Integer>> rowColHeight = new ArrayList<ArrayList<Integer>>(); 

    public EndCycleCellEditor(){ 
     component = new JTextArea(); 
     ((JTextArea) component).setWrapStyleWord(true); 
     ((JTextArea) component).setLineWrap(true); 
     component.addKeyListener(this); 
    } 

    @Override 
    public Object getCellEditorValue() { 
     return ((JTextArea) component).getText(); 
    } 

    @Override 
    public Component getTableCellEditorComponent(JTable table, Object value, 
      boolean isSelected, int row, int column) { 
     ((JTextArea)component).setText(value.toString()); 
     return component; 
    } 

    @Override 
    public void keyTyped(KeyEvent e) { 
     // TODO Auto-generated method stub 

    } 

    @Override 
    public void keyPressed(KeyEvent e) { 
     // TODO Auto-generated method stub 

      } 

    @Override 
    public void keyReleased(KeyEvent e) { 
     if(((JTextArea) component).getText().length() >= 200){ 
      Toolkit.getDefaultToolkit().beep(); 
      ((JTextArea)component).setText(((JTextArea)component).getText().substring(0,200)); 
     } 

    } 



} 

ответ

4

1) размер этот путь возможно, но некрасиво и не user_friendly

2) не использовать non_standard взломать, как Multilines охватывают в JTable

3) положить JTextArea в JScrollPane, но тогда вы должны переопределить прокрутке JScrollPane внутри другого JScrollPane

import java.awt.*; 
import javax.swing.*; 
import javax.swing.table.*; 

class JTableMultiLineSupport extends AbstractCellEditor implements TableCellEditor, TableCellRenderer { 

    private static final long serialVersionUID = 1L; 
    private JTextArea editor = new JTextArea(4, 10); 
    private JScrollPane jsp = new JScrollPane(editor); 
    private JTable table; 
    private int row; 
    private int col; 
    private JTextArea renderer = new JTextArea(4, 10); 

    public static void main(String[] args) { 
     JTable table = new JTable(new String[][]{ 
        {"1\n2\n3\n4\n5\n6\n7", "1\n2\n3\n4\n5\n6\n7", "1\n2\n3\n4\n5\n6\n7"}, 
        {"1\n2\n3\n4\n5\n6\n7", "1\n2\n3\n4\n5\n6\n7", "1\n2\n3\n4\n5\n6\n7"}}, 
       new String[]{"First Column", "Second Column", "Third Column"}); 
     JTableMultiLineSupport mls = new JTableMultiLineSupport(); 
     table.setDefaultEditor(Object.class, mls); 
     table.setDefaultRenderer(Object.class, mls); 
     table.setRowHeight(0, 30); 
     table.setRowHeight(1, 70); 
     table.setPreferredScrollableViewportSize(table.getPreferredSize()); 
     JFrame frame = new JFrame("Test"); 
     frame.add(new JScrollPane(table)); 
     frame.pack(); 
     frame.setVisible(true); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    } 

    @Override 
    public Component getTableCellEditorComponent(JTable table, Object value, 
      boolean isSelected, int row, int col) { 
     this.table = table; 
     this.row = row; 
     this.col = col; 
     editor.setText(value.toString()); 
     return jsp; 
    } 

    @Override 
    public Component getTableCellRendererComponent(JTable table, Object value, 
      boolean isSelected, boolean hasFocus, int row, int column) { 
     renderer.setText(value == null ? "" : value.toString()); 
     renderer.setEnabled(false); 
     return renderer; 
    } 

    @Override 
    public Object getCellEditorValue() { 
     return editor.getText(); 
    } 

    @Override 
    public boolean stopCellEditing() { 
     table.getModel().setValueAt(editor.getText(), row, col); 
     return true; 
    } 
} 
+0

Прошу прощения, какое решение? – Boundless

+0

@Boundless см. Мое редактирование – mKorbel

+0

Любой способ потерять полосы прокрутки и сделать строки увеличивать их высоты при вводе ??? – Igor

0

[EDIT: У моего первоначального ответа были некоторые ошибки и последствия. Между тем, я нашел более элегантное решение, основанное на различных примерах.]

Это решение основано на http://www.coderanch.com/t/336033/GUI/java/MultiLine-JTable - Я сделал некоторые исправления, хотя (В основном: удалено вычисление rowHeights из редактора, добавлено вычисление rowHeight to Renderer) ,

Предложения на http://blog.botunge.dk/post/2009/10/09/JTable-multiline-cell-renderer.aspx хороши, чтобы сделать его более красивым (например, добавление цветов и шрифтов для таблицы).

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

Шаг первый: CellRenderer

public class MultiLineCellRenderer extends JTextArea implements 
    TableCellRenderer { 

public MultiLineCellRenderer() { 
    setEditable(false); 
    setLineWrap(true); 
    setWrapStyleWord(true); 
} 

public Component getTableCellRendererComponent(JTable table, Object value, 
     boolean isSelected, boolean hasFocus, int row, int column) { 

    if (value instanceof String) { 
     setText((String) value); 
     // We set the width and force textarea to recompute the preferred height 
     setSize(table.getColumnModel().getColumn(column).getWidth(), 1000); 

     // we should not do the following in this method. 
     // it seems to create an endless loop 
     // int rowHeight = table.getRowHeight(row); 
     // int cellHeight = getPreferredSize().height; 
     // if (cellHeight > rowHeight) 
     // table.setRowHeight(row, cellHeight); 
    } else 
     setText(""); 
    return this; 
} 

/* 
* Make sure to call this method, whenever the table changes. 
* Call it from appropriate TableCellRenderer, TableModelListener, 
* ComponentListener, TableColumnModelListener. 
*/ 
public void updateRowHeights() { 
    for (int row = 0; row < table.getRowCount(); row++) { 
     int rowHeight = 0; 
     for (int col = 0; col < table.getColumnCount(); col++) { 
      Object value = table.getValueAt(row, col); 
      if (value != null) 
       setText(value.toString()); 
      else 
       setText(""); 
      setSize(table.getColumnModel().getColumn(col).getWidth(), 1000); 
      int cellHeight = getPreferredSize().height; 
      if (cellHeight > rowHeight) 
       rowHeight = cellHeight; 
     } 
     table.setRowHeight(row, rowHeight); 
    } 
} 
} 

Шаг 2: CellEditor (я полагаю, что существует более короткое решение можно, не перекрывая JTextArea).

public class MultiLineCellEditor extends AbstractCellEditor implements 
    TableCellEditor { 
MyTextArea textArea; 
JTable table; 

public MultiLineCellEditor(JTable ta) { 
    super(); 
    table = ta; 
    // this component relies on having this renderer for the String 
    // class 
    MultiLineCellRenderer renderer = new MultiLineCellRenderer(); 
    table.setDefaultRenderer(String.class, renderer); 
    textArea = new MyTextArea(); 
    textArea.setLineWrap(true); 
    textArea.setWrapStyleWord(true); 
} 

public Object getCellEditorValue() { 
    return textArea.getText(); 
} 

public Component getTableCellEditorComponent(JTable table, Object value, 
     boolean isSelected, int row, int column) { 
    textArea.setText(table.getValueAt(row, column).toString()); 
    textArea.rowEditing = row; 
    textArea.columnEditing = column; 
    textArea.lastPreferredHeight = textArea.getPreferredSize().height; 
    return textArea; 
} 

/** 
* This method determines the height in pixel of a cell given the text it 
* contains 
*/ 
private int cellHeight(int row, int col) { 
    if (row == table.getEditingRow() && col == table.getEditingColumn()) 
     return textArea.getPreferredSize().height; 
    else 
     return table 
       .getDefaultRenderer(String.class) 
       .getTableCellRendererComponent(table, 
         table.getModel().getValueAt(row, col), false, 
         false, row, col).getPreferredSize().height; 
} 

void cellGrewEvent(int row, int column) { 
    updateRow(row); 
} 

void cellShrankEvent(int row, int column) { 
    updateRow(row); 
} 

void updateRow(int row) { 
    int maxHeight = 0; 
    for (int j = 0; j < table.getColumnCount(); j++) { 
     int ch; 
     if ((ch = cellHeight(row, j)) > maxHeight) { 
      maxHeight = ch; 
     } 
    } 
    table.setRowHeight(row, maxHeight); 
} 

class MyTextArea extends JTextArea implements KeyListener { 
    private static final long serialVersionUID = 1L; 
    int lastPreferredHeight = 0; 
    int rowEditing; 
    int columnEditing; 

    MyTextArea() { 
     addKeyListener(this); 
     // This is a fix to Bug Id 4256006 
     addAncestorListener(new AncestorListener() { 
      public void ancestorAdded(AncestorEvent e) { 
       requestFocus(); 
      } 

      public void ancestorMoved(AncestorEvent e) { 
      } 

      public void ancestorRemoved(AncestorEvent e) { 
      } 
     }); 
    } 

    public void keyPressed(KeyEvent e) { 
    } 

    public void keyReleased(KeyEvent e) { 
    } 

    public void keyTyped(KeyEvent e) { 
     if (getPreferredSize().getHeight() > lastPreferredHeight) { 
      lastPreferredHeight = getPreferredSize().height; 
      cellGrewEvent(rowEditing, columnEditing); 
      // this will trigger the addition of extra lines upon the 
      // cell growing and prevent all the text being lost when 
      // the cell grows to the point of requiring scrollbars 
      table.setValueAt(getText(), rowEditing, columnEditing); 
     } else if (getPreferredSize().getHeight() < lastPreferredHeight) { 
      lastPreferredHeight = getPreferredSize().height; 
      cellShrankEvent(rowEditing, columnEditing); 
     } else if (table.getValueAt(rowEditing, columnEditing).equals("")) 
      table.setValueAt(getText(), rowEditing, columnEditing); 
    } 
} 
} 

И вот какой-то код для его проверки.

public class MultiLineCellExample extends JFrame { 

private static final long serialVersionUID = 1L; 

public MultiLineCellExample() { 
    DefaultTableModel dm = new DefaultTableModel() { 
     private static final long serialVersionUID = 1L; 

     public Class<?> getColumnClass(int columnIndex) { 
      return String.class; 
     } 
    }; 
    dm.setDataVector(
      new Object[][] { 
        { "aa TEST TEST TEST TEST TEST TEST TEST TEST END", 
          "bb", "cc" }, { "A\nA", "B\nB", "C\nC" } }, 
      new Object[] { "1", "2", "3" }); 
    JTable table = new JTable(dm); 
    MultiLineCellEditor editor = new MultiLineCellEditor(table); 
    table.setDefaultEditor(String.class, editor); 
    dm.fireTableRowsInserted(0, 0); 
    JScrollPane scroll = new JScrollPane(table); 
    getContentPane().add(scroll); 
} 

public static void main(String[] args) { 
    MultiLineCellExample mlce = new MultiLineCellExample(); 

    mlce.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    mlce.setSize(400, 400); 
    mlce.pack(); 
    mlce.setVisible(true); 
} 

} 
+0

Пример не поддается компиляции. –