概要

JTableTableCellEditorとして、JTextAreaJScrollPaneを使用します。

スクリーンショット

ScrollingCellEditor.png

サンプルコード

class TextAreaCellEditor extends AbstractCellEditor implements TableCellEditor {
  private static final String KEY = "Stop-Cell-Editing";
  private final JTextArea textArea = new JTextArea();
  private final JScrollPane scroll = new JScrollPane(textArea);

  protected TextAreaCellEditor() {
    super();
    scroll.setBorder(BorderFactory.createEmptyBorder());
    // scroll.setViewportBorder(BorderFactory.createEmptyBorder());

    textArea.setLineWrap(true);
    textArea.setBorder(BorderFactory.createEmptyBorder(2, 4, 2, 4));

    int modifiers = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
    // Java 10: int modifiers = Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx();
    KeyStroke enter = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, modifiers);
    textArea.getInputMap(JComponent.WHEN_FOCUSED).put(enter, KEY);
    textArea.getActionMap().put(KEY, new AbstractAction() {
      @Override public void actionPerformed(ActionEvent e) {
        stopCellEditing();
      }
    });
  }

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

  @Override public Component getTableCellEditorComponent(
        JTable table, Object value, boolean isSelected, int row, int column) {
    // System.out.println("getTableCellEditorComponent");
    textArea.setFont(table.getFont());
    textArea.setText(Objects.toString(value, ""));
    EventQueue.invokeLater(() -> {
      textArea.setCaretPosition(textArea.getText().length());
      textArea.requestFocusInWindow();
      System.out.println("invokeLater: getTableCellEditorComponent");
    });
    return scroll;
  }

  @Override public boolean isCellEditable(EventObject e) {
    if (e instanceof MouseEvent) {
      return ((MouseEvent) e).getClickCount() >= 2;
    }
    // System.out.println("isCellEditable");
    EventQueue.invokeLater(() -> {
      if (e instanceof KeyEvent) {
        KeyEvent ke = (KeyEvent) e;
        char kc = ke.getKeyChar();
        if (Character.isUnicodeIdentifierStart(kc)) {
          textArea.setText(textArea.getText() + kc);
          System.out.println("invokeLater: isCellEditable");
        }
      }
    });
    return true;
  }
}
View in GitHub: Java, Kotlin

解説

上記のサンプルでは、0列目にデフォルトのTableCellEditor(JTextField)1列目にJTextAreaを継承したTableCellEditorを設定しています。

  • TableCellEditor#isCellEditable(...)
    • マウスのダブルクリックで編集開始
  • TableCellEditor#getTableCellEditorComponent(...)
    • JTextAreaに現在表示されているセル文字列をコピーし、戻り値のComponentとしてJScrollPaneを返す
  • TableCellEditor#isCellEditable(...)EventQueue.invokeLater(...)
  • TableCellEditor#getTableCellEditorComponent(...)EventQueue.invokeLater(...)
    • JTextAreaにフォーカスを移動しJTextAreaのキャレットも文字列末尾に移動

参考リンク

コメント