概要

JLayerを使用してJTableHeaderの列をマウスの右ボタンでドラッグしても順序変更不可に設定します。

サンプルコード

class DisableRightButtonSwapLayerUI extends LayerUI<JScrollPane> {
  @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 JScrollPane> l) {
    int id = e.getID();
    Component c = e.getComponent();
    if (c instanceof JTableHeader &&
         id == MouseEvent.MOUSE_DRAGGED &&
         SwingUtilities.isRightMouseButton(e)) {
      e.consume();
    }
  }
}
View in GitHub: Java, Kotlin

解説

上記のサンプルでは、JTableHeaderの列をマウスの右ボタンでドラッグした場合のみ順序変更不可に設定しています。

  • Default
    • 右ボタンでドラッグ可能なので、JTableHeaderの外部まで列をドラッグしてポップアップメニューを開くと描画が乱れる場合がある
      • JPopupMenu#show(...)メソッドをオーバーライドしてドラッグ中の列をクリア、ヘッダの再描画などを実行して回避する必要がある
    • 列の入れ替えを禁止する場合はtable.getTableHeader().setReorderingAllowed(false);を設定する
  • Disable right mouse button reordering
    • JLayerJTableを配置したJScrollPaneに設定
      • LayerUI#processMouseMotionEvent(...)メソッドをオーバーライドし、JTableHeader上の右ボタンでのドラッグイベントを消費
    • マウスの左、中ボタンでのドラッグは有効
    • マウスの右ボタンをクリックしてJTableHeaderに設定したポップアップメニューを開くことは可能
    • 左ボタンでドラッグ開始、途中で左右両方のボタンを押して右ボタンを後からリリースするとJTableHeaderの外部でポップアップメニューを開くことが可能なので、Defaultと同様にJPopupMenu#show(...)メソッドをオーバーライドしてドラッグ中の列をクリア、ヘッダの再描画などを実行する必要がある
    • [JDK-8068824] Exception thrown in JTableHeader after clicking on popupmenu opened with right-click on header - Java Bug System

参考リンク

コメント