Summary

JTableDate用セルエディタとしてJTableで作成したカレンダーをJPopupMenuに配置して使用することで日付の選択・変更を可能にします。

Source Code Examples

class DateEditor extends AbstractCellEditor implements TableCellEditor, ActionListener {
  private static final String EDIT = "edit";
  private final JButton button = new JButton();
  private final DateFormat formatter = DateFormat.getDateInstance();
  private final CalenderPanel dateChooser = new CalenderPanel();
  private JPopupMenu popup;
  private JTable table;

  protected DateEditor() {
    super();
    button.setActionCommand(EDIT);
    button.addActionListener(this);
    button.setContentAreaFilled(false);
    button.setFocusPainted(false);
    button.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
    button.setHorizontalAlignment(SwingConstants.LEFT);
    button.setHorizontalTextPosition(SwingConstants.RIGHT);
  }

  @Override public void actionPerformed(ActionEvent e) {
    if (EDIT.equals(e.getActionCommand()) && table != null) {
      int row = table.getSelectedRow();
      int col = table.getSelectedColumn();
      Rectangle rect = table.getCellRect(row, col, true);
      Point p = new Point(rect.x, (int) rect.getMaxY());
      if (popup == null) {
        popup = new JPopupMenu();
        popup.add(dateChooser);
        popup.pack();
      }
      popup.show(table, p.x, p.y);
      dateChooser.requestFocusInWindow();
    }
  }

  @Override public boolean isCellEditable(EventObject e) {
    return e instanceof MouseEvent && ((MouseEvent) e).getClickCount() >= 2;
  }

  @Override public Object getCellEditorValue() {
    LocalDate d = dateChooser.getLocalDate();
    return Date.from(d.atStartOfDay(ZoneId.systemDefault()).toInstant());
  }

  @Override public Component getTableCellEditorComponent(
      JTable table, Object value, boolean isSelected, int row, int column) {
    if (value instanceof Date) {
      Date date = (Date) value;
      button.setText(formatter.format(date));
      button.setOpaque(true);
      // button.setForeground(table.getSelectionForeground());
      Color fgc = table.getSelectionForeground();
      button.setForeground(new Color(fgc.getRGB()));
      button.setBackground(table.getSelectionBackground());
      ZonedDateTime dateTime = date.toInstant().atZone(ZoneId.systemDefault());
      dateChooser.setLocalDate(dateTime.toLocalDate());
      this.table = table;
    }
    return button;
  }

  private final class CalenderPanel extends JPanel {
     // ...
  }

  private static final class MonthTable extends JTable {
     // ...
  }

  private static class CalendarTableRenderer extends DefaultTableCellRenderer {
     // ...
  }
}
View in GitHub: Java, Kotlin

Description

  • DateEditor
    • AbstractCellEditorを継承して日付用セルエディタを作成
    • エディタのセル内の表示にはJButtonを使用
    • AbstractCellEditor#isCellEditable(...)をオーバーライドしてマウスでダブルクリックした場合セル編集を開始するよう設定
    • TableCellEditor#getTableCellEditorComponent(...)を実装してDateChooserJButtonに日付などを設定
    • 編集開始でJButtonのクリックイベントが発生するので編集対象セルの下にカレンダーを配置したJPopupMenuを開く
  • CalenderPanelMonthTable

Reference

Comment