Swing/ContinuousMonthlyCalendar の変更点
- 追加された行はこの色です。
- 削除された行はこの色です。
- Swing/ContinuousMonthlyCalendar へ行く。
- Swing/ContinuousMonthlyCalendar の差分を削除
--- category: swing folder: ContinuousMonthlyCalendar title: JScrollPaneにJTableを配置して連続月間カレンダーを作成する tags: [JScrollPane, JTable, LocalDate, Calendar] author: aterai pubdate: 2023-02-27T01:05:27+09:00 description: JScrollPaneにJTableを配置してマウスホイールなどでスクロール可能な連続月間カレンダーを作成します。 image: https://drive.google.com/uc?id=1t_loMpWjMtdCAC6iCBzebKnkdJoiV7pj --- * 概要 [#summary] `JScrollPane`に`JTable`を配置してマウスホイールなどでスクロール可能な連続月間カレンダーを作成します。 #download(https://drive.google.com/uc?id=1t_loMpWjMtdCAC6iCBzebKnkdJoiV7pj) * サンプルコード [#sourcecode] #code(link){{ JScrollBar verticalScrollBar = new JScrollBar(Adjustable.VERTICAL) { @Override public Dimension getPreferredSize() { Dimension d = super.getPreferredSize(); d.width = 0; return d; } }; verticalScrollBar.setUnitIncrement(monthTable.getRowHeight()); scroll.setVerticalScrollBar(verticalScrollBar); verticalScrollBar.getModel().addChangeListener(e -> { EventQueue.invokeLater(() -> { JViewport viewport = scroll.getViewport(); Point pt = SwingUtilities.convertPoint(viewport, 0, 0, monthTable); int row = monthTable.rowAtPoint(pt); int col = 6; // monthTable.columnAtPoint(pt); LocalDate localDate = (LocalDate) monthTable.getValueAt(row, col); currentLocalDate = localDate; updateMonthLabel(localDate, locale1); viewport.repaint(); }); }); }} * 解説 [#explanation] - 表示用の`JTable`や`JTableHeader`、`TableCellRenderer`は[[JTableにLocaleを考慮したLocalDateを適用してカレンダーを表示する>Swing/CalendarViewTable]]とほぼ同じものを使用 -- 行の高さを`32px`固定に変更している - `TableModel`は`1`月`6`週分の`6`行ではなく、現在の日付から前後`500`週分の`1000`行分保持するよう変更し、スクロールで表示する週を変更可能にしている -- このため月変更用`JButton`は`TableModel`の入れ替えではなく、以下のように`monthTable.scrollRectToVisible(...)`メソッドを実行して対象となる月の`1`週目が先頭に表示される位置までスクロールするよう変更 #code{{ public void updateMonthView(LocalDate localDate, Locale locale) { currentLocalDate = localDate; updateMonthLabel(localDate, locale); TableModel model = monthTable.getModel(); int v = model.getRowCount() / 2; LocalDate startDate1 = getTopLeftCellDayOfMonth(realLocalDate, locale); LocalDate startDate2 = getTopLeftCellDayOfMonth(localDate, locale); int between = (int) ChronoUnit.WEEKS.between(startDate1, startDate2); Rectangle r = monthTable.getCellRect(v + between, 0, false); r.height = scroll.getViewport().getViewRect().height; monthTable.scrollRectToVisible(r); scroll.repaint(); } }} - 縦`JScrollBar`はその幅を`0`に設定して不可視化しているが`MouseWheel`でスクロール可能になるよう設定 -- [[JScrollBarが非表示でもMouseWheelでScrollする>Swing/MouseWheelScroll]] - 縦`JScrollBar``ChangeListener`を設定し`MouseWheel`などでスクロールしたとき右上隅に表示されるセルの日付の月を取得して月表示`JLabel`に設定 - 縦`JScrollBar`に`ChangeListener`を追加し`MouseWheel`などでスクロールしたとき右上隅に表示されるセルの日付の月を取得して月表示`JLabel`を更新 -- [[JEditorPaneのスクロールに連動してJTreeのノードを選択する>Swing/Scrollspy]] * 参考リンク [#reference] - [[JTableにLocaleを考慮したLocalDateを適用してカレンダーを表示する>Swing/CalendarViewTable]] - [[JScrollBarが非表示でもMouseWheelでScrollする>Swing/MouseWheelScroll]] - [[JEditorPaneのスクロールに連動してJTreeのノードを選択する>Swing/Scrollspy]] * コメント [#comment] #comment #comment