• category: swing folder: CalendarViewTable title: JTableにLocaleを考慮したLocalDateを適用してカレンダーを表示する tags: [JTable, LocalDate, Locale, Calendar] author: aterai pubdate: 2018-01-29T14:57:32+09:00 description: JTableに週の最初の曜日がLocaleに応じて変化するカレンダーを表示します。 image: https://drive.google.com/uc?id=1jXZtiYFaA5ABWsdaRBnPUKqS2_VBDkFqQA hreflang:
       href: https://java-swing-tips.blogspot.com/2018/01/apply-localdate-considering-locale-to.html
       lang: en

概要

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

サンプルコード

class CalendarViewTableModel<T extends LocalDate> extends DefaultTableModel {
  private final LocalDate startDate;
  private final WeekFields weekFields = WeekFields.of(Locale.getDefault());
  public CalendarViewTableModel(T 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

  • 土曜と日曜の位置も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;
  }
}

参考リンク

コメント