• category: swing folder: ScrollingCellEditor title: TableCellEditorをスクロール可能にする tags: [JTable, JScrollPane, JTextArea, TableCellEditor, Focus] author: aterai pubdate: 2011-06-20T14:39:55+09:00 description: JTableのTableCellEditorとして、JTextAreaとJScrollPaneを使用します。 image: https://lh4.googleusercontent.com/-DDRbJ9WhSJk/Tf7btYjUE7I/AAAAAAAAA9s/yVKIKC55zIw/s800/ScrollingCellEditor.png

概要

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

サンプルコード

class TextAreaCellEditor extends JTextArea implements TableCellEditor {
  private static final String KEY = "Stop-Cell-Editing";
  protected transient ChangeEvent changeEvent;
  private final JScrollPane scroll;

  protected TextAreaCellEditor() {
    super();
    scroll = new JScrollPane(this);
    scroll.setBorder(BorderFactory.createEmptyBorder());
    //scroll.setViewportBorder(BorderFactory.createEmptyBorder());

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

    KeyStroke enter = KeyStroke.getKeyStroke(
        KeyEvent.VK_ENTER, InputEvent.CTRL_DOWN_MASK);
    getInputMap(JComponent.WHEN_FOCUSED).put(enter, KEY);
    getActionMap().put(KEY, new AbstractAction() {
      @Override public void actionPerformed(ActionEvent e) {
        stopCellEditing();
      }
    });
  }
  @Override public Object getCellEditorValue() {
    return getText();
  }
  @Override public Component getTableCellEditorComponent(
      JTable table, Object value, boolean isSelected, int row, int column) {
    System.out.println("getTableCellEditorComponent");
    setFont(table.getFont());
    setText(Objects.toString(value, ""));
    EventQueue.invokeLater(new Runnable() {
      @Override public void run() {
        setCaretPosition(getText().length());
        requestFocusInWindow();
        System.out.println("invokeLater: getTableCellEditorComponent");
      }
    });
    return scroll;
  }
  @Override public boolean isCellEditable(final EventObject e) {
    if (e instanceof MouseEvent) {
      return ((MouseEvent) e).getClickCount() >= 2;
    }
    System.out.println("isCellEditable");
    EventQueue.invokeLater(new Runnable() {
      @Override public void run() {
        if (e instanceof KeyEvent) {
          KeyEvent ke = (KeyEvent) e;
          char kc = ke.getKeyChar();
          if (Character.isUnicodeIdentifierStart(kc)) {
            setText(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
    • キー入力で編集開始した場合、その入力をJTextAreaの文字列末尾に追加
  • TableCellEditor#getTableCellEditorComponent, EventQueue.invokeLater
    • JTextAreaにフォーカスを移動し、JTextAreaのキャレットも文字列末尾に移動

参考リンク

コメント