概要

JTableに週の最初の曜日がLocaleに応じて変化するカレンダーを表示します。

サンプルコード

class CalendarViewTableModel extends DefaultTableModel {
  private final LocalDate startDate;
  private final WeekFields weekFields = WeekFields.of(Locale.getDefault());

  public CalendarViewTableModel(LocalDate date) {
    super();
    LocalDate firstDayOfMonth = YearMonth.from(date).atDay(1);
    int dowv = firstDayOfMonth.get(weekFields.dayOfWeek()) - 1;
    startDate = firstDayOfMonth.minusDays(dowv);
  }

  @Override public Class<?> getColumnClass(int column) {
    return LocalDate.class;
  }

  @Override public String getColumnName(int column) {
    return weekFields.getFirstDayOfWeek().plus(column)
      .getDisplayName(TextStyle.SHORT_STANDALONE, Locale.getDefault());
  }

  @Override public int getRowCount() {
    return 6;
  }

  @Override public int getColumnCount() {
    return 7;
  }

  @Override public Object getValueAt(int row, int column) {
    return startDate.plusDays(row * getColumnCount() + column);
  }

  @Override public boolean isCellEditable(int row, int column) {
    return false;
  }
}
View in GitHub: Java, Kotlin

解説

上記のサンプルでは、Java 8からjava.timeパッケージに追加されたLocalDateJTableのモデルとして使用し、月のカレンダーを表示しています。

  • WeekFields#getFirstDayOfWeek()メソッドでLocaleに応じた週の最初の曜日を取得してJTable0列目を設定
    • 週の最初の曜日はロケールがフランスやISO-8601標準の場合は月曜日、アラビアなら土曜日になる

java -Duser.language=fr -jar example.jar

java -Duser.language=ar -jar example.jar

  • 土曜と日曜の位置も6列目と0列目固定ではないので、以下のようにLocalDate.getDayOfWeek()メソッドで曜日を確認してその背景色を変更する必要がある
private class CalendarTableRenderer extends DefaultTableCellRenderer {
  @Override public Component getTableCellRendererComponent(
      JTable table, Object value, boolean selected, boolean focused,
      int row, int column) {
    super.getTableCellRendererComponent(table, value, selected, focused, row, column);
    setHorizontalAlignment(SwingConstants.CENTER);
    if (value instanceof LocalDate) {
      LocalDate d = (LocalDate) value;
      setText(String.valueOf(d.getDayOfMonth()));
      if (YearMonth.from(d).equals(YearMonth.from(currentLocalDate))) {
        setForeground(Color.BLACK);
      } else {
        setForeground(Color.GRAY);
      }
      DayOfWeek dow = d.getDayOfWeek();
      if (d.isEqual(realLocalDate)) {
        setBackground(new Color(220, 255, 220));
      } else if (dow == DayOfWeek.SUNDAY) {
        setBackground(new Color(255, 220, 220));
      } else if (dow == DayOfWeek.SATURDAY) {
        setBackground(new Color(220, 220, 255));
      } else {
        setBackground(Color.WHITE);
      }
    }
    return this;
  }
}

参考リンク

コメント