Swing/RoundedSelectionListCalendar のバックアップ(No.2)
- バックアップ一覧
- 差分 を表示
- 現在との差分 を表示
- 現在との差分 - Visual を表示
- ソース を表示
- Swing/RoundedSelectionListCalendar へ行く。
- 1 (2024-04-15 (月) 05:49:52)
- 2 (2024-04-15 (月) 12:39:22)
- 3 (2024-04-30 (火) 17:45:30)
- 4 (2024-10-03 (木) 02:04:28)
- 5 (2024-10-03 (木) 09:27:09)
- category: swing folder: RoundedSelectionListCalendar title: JListで作成したカレンダーのセル選択領域を角丸で描画する tags: [JList, Path2D, Graphics, Calendar] author: aterai pubdate: 2024-04-15T05:49:23+09:00 description: JListで作成したカレンダーでセルを複数選択した領域のすべての角を丸めて描画します。 image: https://drive.google.com/uc?id=1Mmv2sjRe4isN64Nwl_0FyI9ZRedoCJMX
概要
JList
で作成したカレンダーでセルを複数選択した領域のすべての角を丸めて描画します。
Screenshot
Advertisement
サンプルコード
/**
Rounding the corners of a Rectilinear Polygon.
*/
public static Path2D convertRoundedPath(List<Point2D> list, double arc) {
double kappa = 4d * (Math.sqrt(2d) - 1d) / 3d; // = 0.55228...;
double akv = arc - arc * kappa;
int sz = list.size();
Point2D pt0 = list.get(0);
Path2D path = new Path2D.Double();
path.moveTo(pt0.getX() + arc, pt0.getY());
for (int i = 0; i < sz; i++) {
Point2D prv = i == 0 ? list.get(sz - 1) : list.get(i - 1);
Point2D cur = list.get(i);
Point2D nxt = i < sz - 1 ? list.get(i + 1) : list.get(0);
double dx0 = Math.signum(cur.getX() - prv.getX());
double dy0 = Math.signum(cur.getY() - prv.getY());
double dx1 = Math.signum(nxt.getX() - cur.getX());
double dy1 = Math.signum(nxt.getY() - cur.getY());
path.curveTo(
cur.getX() - dx0 * akv, cur.getY() - dy0 * akv,
cur.getX() + dx1 * akv, cur.getY() + dy1 * akv,
cur.getX() + dx1 * arc, cur.getY() + dy1 * arc
);
path.lineTo(nxt.getX() - dx1 * arc, nxt.getY() - dy1 * arc);
}
path.closePath();
return path;
}
View in GitHub: Java, Kotlin解説
- JListで月のカーソルキー移動や、週を跨いた日付を範囲選択が可能なカレンダーを作成するの
JList
を使用 - セルの選択状態、フォーカス状態に関係なく背景色を描画しないセルレンダラーを設定し、代わりに
JList#paintComponent(...)
をオーバーライドしてセルの選択状態を描画 ListSelectionModel.SINGLE_INTERVAL_SELECTION
で1
つの連続区間のみを選択可能に設定JList#getCellBounds(...)
で選択セル領域を取得し、Area#add(new Area(Rectangle))
でひとつのArea
にまとめる- まとめられた選択領域の
Area
は直角多角形(任意の内角が90°
または270°
で辺が直角に交わる)になるので、これらの角(Point2D
)をすべてPath2D.curveTo(...)
で丸めたPath2D
に変換
public final JList<LocalDate> monthList = new JList<LocalDate>() {
@Override public void updateUI() {
setCellRenderer(null);
super.updateUI();
setLayoutOrientation(HORIZONTAL_WRAP);
setVisibleRowCount(CalendarViewListModel.ROW_COUNT);
setFixedCellWidth(size.width);
setFixedCellHeight(size.height);
setCellRenderer(new CalendarListRenderer());
setOpaque(false);
getSelectionModel().setSelectionMode(
ListSelectionModel.SINGLE_INTERVAL_SELECTION);
addListSelectionListener(e -> repaint());
}
@Override protected void paintComponent(Graphics g) {
int[] indices = getSelectedIndices();
if (indices != null && indices.length > 0) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setPaint(SELECTED_COLOR);
Area area = new Area();
Arrays.stream(indices)
.mapToObj(i -> getCellBounds(i, i))
.forEach(r -> area.add(new Area(r)));
List<Point2D> lst = GeomUtils.convertAreaToPoint2DList(area);
g2.fill(GeomUtils.convertRoundedPath(lst, 4d));
g2.dispose();
}
super.paintComponent(g);
}
};