2012-01-23 27 views
2

我有一個可編輯的JTable。當用戶輸入時,如果文本比寬度更長,我需要增加高度。我已經將linewrap設置爲true,但它僅在用戶按下Enter後更改高度。我錯過了什麼?我已經看過該解決大小調整問題的答案(如在cellRenderer的this,但我需要調整高度的用戶類型,他們完成打字而不是之後。如何在用戶鍵入時調整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劈爲多線JTable中

3)把JTextAreaJScrollPane跨越,但你必須要超控滾動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

[編輯:我最初的答案有一些錯誤和暗示。同時,我發現了一個更好的解決方案,基於各種實例]

該解決方案是基於http://www.coderanch.com/t/336033/GUI/java/MultiLine-JTable - 我做了一些錯誤修正,雖然。(晴:從編輯器刪除rowHeights中的計算,增加的rowHeight的計算來渲染器) 。

關於http://blog.botunge.dk/post/2009/10/09/JTable-multiline-cell-renderer.aspx的建議很棒,可以讓它更漂亮(例如添加表格的顏色和字體)。

放在一起,此解決方案呈現多行JTable單元格。當輸入或刪除文本時,編輯器會自動更新行高。行高度的計算留給TextArea的preferredSize。

步驟之一:將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中(I假設有一個較短的解決方案成爲可能,而無需重寫的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

該示例不可編譯。 –

相關問題