• category: swing folder: DisableRightDoubleClickMaximize title: JInternalFrameのタイトルを右ダブルクリックしても最大化しないよう設定する tags: [JInternalFrame, JDesktopPane, JLayer, JPopupMenu] author: aterai pubdate: 2021-09-06T06:25:10+09:00 description: JInternalFrameのタイトルバーをマウスの右ボタンでダブルクリックしても最大化しないよう設定します。 image: https://drive.google.com/uc?id=1GTvnCmjM652oDX-Ncal6SVoBNtXxxwvd

概要

JInternalFrameのタイトルバーをマウスの右ボタンでダブルクリックしても最大化しないよう設定します。

サンプルコード

class DesktopLayerUI extends LayerUI<JDesktopPane> {
  @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 JDesktopPane> l) {
    Component c = e.getComponent();
    Container p = SwingUtilities.getAncestorOfClass(BasicInternalFrameTitlePane.class, c);
    boolean b = c instanceof BasicInternalFrameTitlePane || p instanceof BasicInternalFrameTitlePane;
    boolean isRight = SwingUtilities.isRightMouseButton(e);
    if (b && isRight && e.getID() == MouseEvent.MOUSE_CLICKED && e.getClickCount() >= 2) {
      e.consume();
    }
  }

  @Override protected void processMouseMotionEvent(MouseEvent e, JLayer<? extends JDesktopPane> l) {
    boolean b = e.getComponent() instanceof JInternalFrame;
    boolean isRight = SwingUtilities.isRightMouseButton(e);
    if (b && isRight && e.getID() == MouseEvent.MOUSE_DRAGGED) {
      e.consume();
    }
  }
}
View in GitHub: Java, Kotlin

解説

  • Default
    • Windows環境でWindowsLookAndFeelを使用する場合でもJInternalFrameのタイトルバーをマウスの右ボタンでダブルクリックするとそのJInternalFrameが最大化してしまう
  • JPopupMenu
    • *1.getNorthPane()でタイトルバーを取得し、JComponent#setComponentPopupMenu(popup)JPopupMenuを設定するとマウスの右ボタンクリックでJPopupMenuが開くので右ボタンのダブルクリックによる最大化は実行不可能になる
    • JInternalFrameにJPopupMenuを設定してタイトルを変更する
    • タイトルバーからJPopupMenuを開き、Escキー入力や別コンポーネントをクリックしてポップアップ表示をキャンセルすると再度タイトルバーを左クリックするまでJInternalFrameのリサイズが不可能になるバグ?が存在する
  • WindowsInternalFrameUI
    • WindowsInternalFrameUI#createBorderListener(...)メソッドをオーバーライドして MouseInputAdapterを継承するBorderListenerがマウスの左ボタンにのみ反応するよう変更することで右ボタンのダブルクリックによる最大化を無効にする
      JInternalFrame f = new JInternalFrame("WindowsInternalFrameUI", true, true, true, true) {
        @Override public void updateUI() {
          super.updateUI();
          setUI(new WindowsInternalFrameUI(this) {
            @Override protected MouseInputAdapter createBorderListener(JInternalFrame w) {
              return new BorderListener() {
                @Override public void mouseClicked(MouseEvent e) {
                  if (SwingUtilities.isLeftMouseButton(e)) {
                    super.mouseClicked(e);
                  }
                }
      
                @Override public void mousePressed(MouseEvent e) {
                  if (SwingUtilities.isLeftMouseButton(e)) {
                    super.mousePressed(e);
                  }
                }
              };
            }
          });
        }
      };
      
  • JLayer
    • JDesktopPaneJLayerを被せてJInternalFrameのタイトルバーがマウスの右ボタンでダブルクリックされた場合のマウスイベントを無視する
    • JInternalFrameのシステムアイコンがダブルクリックされるとJInternalFrameは非表示になるが、このJLayerでは合わせてマウスの右ボタンでダブルクリックを無視するよう設定
    • さらにマウスの右ボタンでのJInternalFrameのリサイズも無効化している

参考リンク

コメント