Swing/DragScrollLayer のバックアップ(No.9)
- バックアップ一覧
- 差分 を表示
- 現在との差分 を表示
- 現在との差分 - Visual を表示
- ソース を表示
- Swing/DragScrollLayer へ行く。
- 1 (2013-08-05 (月) 11:49:22)
- 2 (2013-08-06 (火) 13:26:01)
- 3 (2013-08-07 (水) 20:02:01)
- 4 (2014-11-21 (金) 18:11:05)
- 5 (2015-02-03 (火) 16:22:29)
- 6 (2016-08-11 (木) 21:31:34)
- 7 (2016-09-29 (木) 17:14:01)
- 8 (2017-03-28 (火) 15:10:45)
- 9 (2017-03-29 (水) 19:48:54)
- 10 (2018-02-28 (水) 19:07:59)
- 11 (2020-03-04 (水) 16:54:39)
- 12 (2021-08-17 (火) 20:09:08)
- category: swing folder: DragScrollLayer title: JScrollPane内にある複数Componentを配置したJPanelをJLayerを使ってドラッグスクロール tags: [JScrollPane, JPanel, JLayer] author: aterai pubdate: 2013-08-05T11:49:22+09:00 description: 複数のネストしたComponentを配置したJPanelのドラッグイベントを、JScrollPaneをラップしたJLayerで受け取ってスクロール可能にします。 image:
概要
複数のネストしたComponent
を配置したJPanel
のドラッグイベントを、JScrollPane
をラップしたJLayer
で受け取ってスクロール可能にします。
Screenshot
Advertisement
サンプルコード
class DragScrollLayerUI extends LayerUI<JScrollPane> {
private final Point pp = new Point();
@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 JScrollPane> l) {
Component c = e.getComponent();
if (c instanceof JScrollBar || c instanceof JSlider) {
return;
}
if (e.getID() == MouseEvent.MOUSE_PRESSED) {
JViewport vport = l.getView().getViewport();
Point cp = SwingUtilities.convertPoint(c, e.getPoint(), vport);
pp.setLocation(cp);
}
}
@Override protected void processMouseMotionEvent(
MouseEvent e, JLayer<? extends JScrollPane> l) {
Component c = e.getComponent();
if (c instanceof JScrollBar || c instanceof JSlider) {
return;
}
if (e.getID() == MouseEvent.MOUSE_DRAGGED) {
JViewport vport = l.getView().getViewport();
JComponent cmp = (JComponent) vport.getView();
Point cp = SwingUtilities.convertPoint(c, e.getPoint(), vport);
Point vp = vport.getViewPosition();
vp.translate(pp.x - cp.x, pp.y - cp.y);
cmp.scrollRectToVisible(new Rectangle(vp, vport.getSize()));
pp.setLocation(cp);
}
}
}
View in GitHub: Java, Kotlin解説
DragScrollListener
(左)- JTreeの余白をドラッグしてスクロール
- このリスナーを追加した一つの
Component
をドラッグしてスクロールが可能 JPanel
を掴んでのスクロールが実行可能だが、その子コンポーネントのJTabbedPane
などをドラッグしてもスクロールは不可
DragScrollLayer
(右)- すべての下位コンポーネントの
MouseEvent
をキャッチするようJLayer#setLayerEventMask(...)
と設定したJLayer
を作成 - この
JLayer
でJScrollPane
をラップし、子にマウスイベントを消費するコンポーネントがあっても、ビューであるJPanel
をドラッグに応じてスクロール JScrollBar
やJSlider
のように、ノブのドラッグを使用するコンポーネントは二重にスクロールしてしまうので除外
- すべての下位コンポーネントの
参考リンク
- Java Swing Tips: Mouse Dragging ViewPort Scroll
- JTreeの余白をドラッグしてスクロール
- JScrollPaneのViewportをマウスで掴んでスクロール