概要
JList
を垂直方向ニュースペーパー・スタイルレイアウトに設定してウィークカレンダーを作成し、これにヒートマップを表示します。
Screenshot
Advertisement
サンプルコード
JList<Contribution> weekList = new JList<Contribution>() {
@Override public void updateUI() {
setCellRenderer(null);
super.updateUI();
setLayoutOrientation(JList.VERTICAL_WRAP);
setVisibleRowCount(DayOfWeek.values().length); // ensure 7 rows in the list
setFixedCellWidth(size.width);
setFixedCellHeight(size.height);
setCellRenderer(new ContributionListRenderer());
getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
}
};
// ...
private class ContributionListRenderer implements ListCellRenderer<Contribution> {
private final Icon emptyIcon = new ColorIcon(Color.WHITE);
private final ListCellRenderer<? super Contribution> renderer
= new DefaultListCellRenderer();
@Override public Component getListCellRendererComponent(
JList<? extends Contribution> list, Contribution value, int index,
boolean isSelected, boolean cellHasFocus) {
JLabel l = (JLabel) renderer.getListCellRendererComponent(
list, null, index, isSelected, cellHasFocus);
if (value.date.isAfter(currentLocalDate)) {
l.setIcon(emptyIcon);
l.setToolTipText(null);
} else {
l.setIcon(activityIcons.get(value.activity));
String actTxt = value.activity == 0 ? "No" : Objects.toString(value.activity);
l.setToolTipText(actTxt + " contribution on " + value.date.toString());
}
return l;
}
}
View in GitHub: Java, Kotlin解説
上記のサンプルでは、セルが垂直方向の次に水平方向の順で並ぶ「ニュースペーパー・スタイル」レイアウトのJList
を使用して、GitHub
で表示されているContribution activity
風のヒートマップカレンダーを作成しています。
1
列で1
週間になるようJList.VERTICAL_WRAP
スタイルでの行数をJList#setVisibleRowCount(7)
で指定WeekFields#getFirstDayOfWeek()
メソッドでLocale
に応じた週の最初の曜日を取得してJList
の0
行目を設定public static final int WEEK_VIEW = 27; // ... WeekFields weekFields = WeekFields.of(Locale.getDefault()); int dow = today.get(weekFields.dayOfWeek()); startDate = today.minusWeeks(WEEK_VIEW - 1).minusDays(dow - 1);
- 表示される週は約半年分の
27
週に設定JList
のindex = 0
となるセルの日付は27
週から今週の1
週間分を引いた26
週前をtoday.minusWeeks(26)
で取得し、さらに今日が週の何番目かを引き算して求める- 週番号を
today.get(weekFields.dayOfWeek())
で取得すると最初の曜日が1
から始まるので、これを-1
して最初の曜日がJList
の0
行目からになるよう変更
- 週番号を
- ヒートマップは、テキストを空にして色アイコンを設定した
JLabel
をListCellRenderer#getListCellRendererComponent(...)
メソッドで返すことで表示- 各日付の色は
4
段階でランダムに生成 - ツールチップテキストも、この
ListCellRenderer
のJLabel
に設定
- 各日付の色は
- 行ヘッダ
- セルサイズが同じ
JList
を適用 - この
JList
のフォントサイズをセルの高さを基準に変更
- セルサイズが同じ
- 列ヘッダ
GridBagLayout
を使用するJPanel
を適用- セルと幅が同じで高さが
0
のレイアウト用ガイドコンポーネントBox.createHorizontalStrut(CELL_SIZE.width)
を作成し、ガイドグリッドとして27
週分追加 - 前の週と月が異なる列に
gridwidth=3
の幅を占有するJLabel
で月名を表示- 月内の週が
4
列、5
列になる場合でも月名JLabel
は3
列分のみ使用し、空列はガイドグリッドで幅を確保 27 - 3 + 1
列目以降は3
列確保できないので月が変わっても月名JLabel
を表示しない
- 月内の週が
参考リンク
- JListで月のカーソルキー移動や、週を跨いた日付を範囲選択が可能なカレンダーを作成する
- こちらはセルが水平方向の次に垂直方向の順で並ぶ「ニュースペーパー・スタイル」レイアウトの
JList
で月カレンダーを表示
- こちらはセルが水平方向の次に垂直方向の順で並ぶ「ニュースペーパー・スタイル」レイアウトの
- Harmonic Code: Friday Fun XLVIII - Calendar Heatmap
- JToolTipを半透明にする
ToolTip
もGitHub
のContribution activity
風に半透明の吹き出しを上側に表示するよう変更
- JListでドットマトリクスLEDデジタル時計を作成する