TITLE:CellEditorをJSpinnerにして日付を変更

CellEditorをJSpinnerにして日付を変更

Posted by terai at 2008-09-22

概要

JTableで、日付を表示する列のセルエディタをJSpinnerにします。

  • &jnlp;
  • &jar;
  • &zip;

#screenshot

サンプルコード

class SpinnerCellEditor extends AbstractCellEditor implements TableCellEditor {
  private final JSpinner spinner = new JSpinner(new SpinnerDateModel());
  private final JSpinner.DateEditor editor;
  public SpinnerCellEditor() {
    editor = new JSpinner.DateEditor(spinner, "yyyy/MM/dd");
    spinner.setEditor(editor);
    setArrowButtonEnabled(false);
    spinner.addFocusListener(new FocusAdapter() {
      public void focusGained(FocusEvent e) {
        //System.out.println("spinner");
        editor.getTextField().requestFocusInWindow();
      }
    });
    editor.getTextField().addFocusListener(new FocusAdapter() {
      //@Override
      public void focusLost(FocusEvent e) {
        setArrowButtonEnabled(false);
      }
      //@Override
      public void focusGained(FocusEvent e) {
        //System.out.println("getTextField");
        setArrowButtonEnabled(true);
        EventQueue.invokeLater(new Runnable() {
          public void run() {
            editor.getTextField().setCaretPosition(8);
            editor.getTextField().setSelectionStart(8);
            editor.getTextField().setSelectionEnd(10);
          }
        });
      }
    });
    spinner.setBorder(BorderFactory.createEmptyBorder(0,0,0,0));
  }
  private void setArrowButtonEnabled(boolean flag) {
    for(Component c: spinner.getComponents()) {
      if(c instanceof JButton) {
        ((JButton)c).setEnabled(flag);
      }
    }
  }
  public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
    spinner.setValue(value);
    editor.getTextField().setHorizontalAlignment(JFormattedTextField.LEFT);
    //JTextField tf = editor.getTextField();
    //tf.setCaretPosition(8);
    //tf.setSelectionStart(8);
    //tf.setSelectionEnd(10);
    return spinner;
  }
  public Object getCellEditorValue() {
    return spinner.getValue();
  }
  public boolean isCellEditable(EventObject e) {
    if(e instanceof MouseEvent) {
      return ((MouseEvent)e).getClickCount() >= 2;
    }
    return true;
  }
}

解説

TableModel#getColumnClass(int)で、第2列目が日付(Date.class)を返すように設定し、JTable#setDefaultEditor(Class,CellEditor)メソッドで上記のセルエディタイを関連付けています。

table.setDefaultEditor(Date.class, new SpinnerCellEditor());
table.setSurrendersFocusOnKeystroke(true);

この日付用のセルエディタ(SpinnerCellEditor)は、以下のような動作になっています。

  • スピナエディタで左寄せ
    • セルレンダラーと合わせるため
    • 1.6.0_07, 1.6.0_06, 1.5.0_16などで、JSpinner(WindowsL&F)の文字サイズ、余白が微妙に異なる?
  • ダブルクリックで編集開始
  • 編集開始時のキャレットは先頭の年(yyyy)ではなく日(dd)で、日(dd)が選択状態になる
    • スピナボタン、上下キーなどで、日(dd)から値が変更されるようにするため
  • 編集開始時、スピナエディタにフォーカスが無い場合は、スピナボタンはクリック不可
    • 編集開始と同時に、スピナボタンが押されて日付が変更されるのを防止するため

コメント