概要

JToolBarのドラッグアウト開始を左マウスボタンでのみ可能になるよう制限します。

サンプルコード

class DockingListener2 extends MouseInputAdapter {
  private final JToolBar toolBar;
  private final MouseInputListener listener;

  protected DockingListener2(JToolBar toolBar, MouseInputListener listener) {
    super();
    this.toolBar = toolBar;
    this.listener = listener;
  }

  private boolean cancelDrag(MouseEvent e) {
    return !toolBar.isEnabled() || !SwingUtilities.isLeftMouseButton(e);
  }

  @Override public void mousePressed(MouseEvent e) {
    if (cancelDrag(e)) {
      return;
    }
    listener.mousePressed(e);
  }

  @Override public void mouseDragged(MouseEvent e) {
    if (cancelDrag(e)) {
      return;
    }
    listener.mouseDragged(e);
  }

  @Override public void mouseReleased(MouseEvent e) {
    if (cancelDrag(e)) {
      return;
    }
    listener.mouseReleased(e);
  }
}
View in GitHub: Java, Kotlin

解説

  • Default
    • デフォルトのJToolBarは左マウスボタンだけでなく右・中マウスボタンのクリックでもドラッグアウト開始が可能
    • このためWindowsLookAndFeel環境などでJToolBarJPopupMenuを設定して右マウスボタンでドラッグアウトするとJToolBarは元の位置に残ったままドラッグ中のJWindowも表示され続ける状態になる
      • 再度左マウスボタンでJToolBarをドラッグアウトし直さないとドラッグ中のJWindowを非表示に戻せないバグ?
  • Override createDockingListener()
    • BasicToolBarUI#createDockingListener()をオーバーライドして右マウスボタンでのドラッグアウトはキャンセルするよう設定
    • このサンプルではBasicToolBarUIJToolBarに設定しているので、子のJButtonLookAndFeelがデフォルトのJToolBarに配置したJButtonとは異なる描画になっている
  • DisableRightButtonDraggedOut
    • JLayerを使用して右マウスボタンでのドラッグアウトはキャンセルするよう設定
    • JToolBarに直接JLayerを設定するとドラッグで配置を変更したときに例外が発生するので、JToolBarの親JPanelJLayerを設定する必要がある
    • このサンプルではJToolBarの名前がDisableRightButtonDraggedOutと一致する場合のみ右マウスボタンでのドラッグアウトを無効化している
    • 左マウスボタンでドラッグアウトを開始して右マウスボタンをプレス、左マウスボタンをリリース、右マウスボタンをリリースするとデフォルトのJToolBarと同様に非表示化できないドラッグ中のJWindowが生成されてしまう
      class DisableRightButtonDragOutLayerUI extends LayerUI<JPanel> {
        @Override public void installUI(JComponent c) {
          super.installUI(c);
          if (c instanceof JLayer) {
            ((JLayer<?>) c).setLayerEventMask(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 processMouseMotionEvent(
              MouseEvent e, JLayer<? extends JPanel> l) {
          Component c = e.getComponent();
          if (c instanceof JToolBar) {
            boolean dragEvent = e.getID() == MouseEvent.MOUSE_DRAGGED;
            boolean leftButton = SwingUtilities.isLeftMouseButton(e);
            boolean checkName = "DisableRightButtonDraggedOut".equals(c.getName());
            if (dragEvent && !leftButton && checkName) {
              e.consume();
            }
          }
        }
      }
      

参考リンク

コメント