Swing/ResizeTabAreaByDragging のバックアップ(No.1)
- バックアップ一覧
- 差分 を表示
- 現在との差分 を表示
- 現在との差分 - Visual を表示
- ソース を表示
- Swing/ResizeTabAreaByDragging へ行く。
- 1 (2021-03-22 (月) 00:11:12)
- 2 (2021-04-30 (金) 15:18:59)
- category: swing folder: ResizeTabAreaByDragging title: JTabbedPaneのタブ領域をマウスドラッグでリサイズする tags: [JTabbedPane, JLayer] author: aterai pubdate: 2021-03-22T00:07:38+09:00 description: JTabbedPaneのタブ領域をマウスで選択、ドラッグしてリサイズします。 image: https://drive.google.com/uc?id=
概要
JTabbedPaneのタブ領域をマウスで選択、ドラッグしてリサイズします。
Screenshot
Advertisement
サンプルコード
class TabAreaResizeLayer extends LayerUI<ClippedTitleTabbedPane> {
private int offset;
private boolean resizing;
@Override public void installUI(JComponent c) {
super.installUI(c);
if (c instanceof JLayer) {
((JLayer<?>) c).setLayerEventMask(AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK);
}
}
@Override public void uninstallUI(JComponent c) {
if (c instanceof JLayer) {
((JLayer<?>) c).setLayerEventMask(0);
}
super.uninstallUI(c);
}
@Override protected void processMouseEvent(
MouseEvent e, JLayer<? extends ClippedTitleTabbedPane> l) {
ClippedTitleTabbedPane tabbedPane = l.getView();
if (e.getID() == MouseEvent.MOUSE_PRESSED) {
Rectangle rect = getDividerBounds(tabbedPane);
Point pt = e.getPoint();
SwingUtilities.convertPoint(e.getComponent(), pt, tabbedPane);
if (rect.contains(pt)) {
offset = pt.x - tabbedPane.getTabAreaWidth();
tabbedPane.setCursor(Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR));
resizing = true;
e.consume();
}
} else if (e.getID() == MouseEvent.MOUSE_RELEASED) {
tabbedPane.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
resizing = false;
}
}
@Override protected void processMouseMotionEvent(
MouseEvent e, JLayer<? extends ClippedTitleTabbedPane> l) {
ClippedTitleTabbedPane tabbedPane = l.getView();
Point pt = e.getPoint();
SwingUtilities.convertPoint(e.getComponent(), pt, tabbedPane);
if (e.getID() == MouseEvent.MOUSE_MOVED) {
Rectangle r = getDividerBounds(tabbedPane);
Cursor c = Cursor.getPredefinedCursor(
r.contains(pt) ? Cursor.W_RESIZE_CURSOR : Cursor.DEFAULT_CURSOR);
tabbedPane.setCursor(c);
} else if (e.getID() == MouseEvent.MOUSE_DRAGGED && resizing) {
tabbedPane.setTabAreaWidth(pt.x - offset);
e.consume();
}
}
private static Rectangle getDividerBounds(ClippedTitleTabbedPane tabbedPane) {
Dimension dividerSize = new Dimension(4, 4);
Rectangle bounds = tabbedPane.getBounds();
Rectangle compRect = Optional.ofNullable(tabbedPane.getSelectedComponent())
.map(Component::getBounds).orElseGet(Rectangle::new);
switch (tabbedPane.getTabPlacement()) {
case SwingConstants.LEFT:
bounds.x = compRect.x - dividerSize.width;
bounds.width = dividerSize.width * 2;
break;
case SwingConstants.RIGHT:
bounds.x += compRect.x + compRect.width - dividerSize.width;
bounds.width = dividerSize.width * 2;
break;
case SwingConstants.BOTTOM:
bounds.y += compRect.y + compRect.height - dividerSize.height;
bounds.height = dividerSize.height * 2;
break;
default: // case SwingConstants.TOP:
bounds.y = compRect.y - dividerSize.height;
bounds.height = dividerSize.height * 2;
break;
}
return bounds;
}
}
View in GitHub: Java, Kotlin解説
JTabbedPane
JTabbedPane#doLayout()
メソッドをオーバーライドしてすべてのタブコンポーネントの推奨サイズを変更することでタブ領域のサイズを変更- ただしタブコンポーネントなどの最小サイズ、最大サイズは考慮せず固定値でタブ領域の最小・最大サイズを決定している
- 現状タブ領域が
SwingConstants.LEFT
の場合のみ対応
- 現状タブ領域が
JLayer
JTabbedPane
にJLayer
を設定してタブ領域とコンポーネント領域の境界をドラッグ可能に設定LayerUI#processMouseEvent(...)
ではタブの子コンポーネントへのマウスイベントも取得可能なので、マウスカーソルの位置はSwingUtilities.convertPoint(e.getComponent(), pt, layer.getView())
でイベントソースコンポーネント(e.getComponent()
で取得したJTabbedPane
自身、またはその子コンポーネント)からJTabbedPane
(JLayer#getView()
で取得可能)の座標に変換する必要がある