• category: swing folder: PreventChangingTabsByInput title: JTabbedPaneでマウスやキー入力によるタブ切替を無効にする tags: [JTabbedPane, JLayer] author: aterai pubdate: 2018-05-14T16:52:16+09:00 description: JTabbedPaneでマウスクリックやキー入力といったユーザ操作イベントによるタブ切替を無効にします。 image: https://drive.google.com/uc?id=16r3rq9ec_trXinEuHffylP6ycwwlGFUGaw

概要

JTabbedPaneでマウスクリックやキー入力といったユーザ操作イベントによるタブ切替を無効にします。

サンプルコード

class DisableInputLayerUI extends LayerUI<Component> {
  @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
        | AWTEvent.MOUSE_WHEEL_EVENT_MASK | AWTEvent.KEY_EVENT_MASK
        | AWTEvent.FOCUS_EVENT_MASK | AWTEvent.COMPONENT_EVENT_MASK);
    }
  }
  @Override public void uninstallUI(JComponent c) {
    if (c instanceof JLayer) {
      ((JLayer<?>) c).setLayerEventMask(0);
    }
    super.uninstallUI(c);
  }
  @Override public void eventDispatched(AWTEvent e, JLayer<? extends Component> l) {
    if (e instanceof InputEvent && Objects.equals(l.getView(), e.getSource())) {
      ((InputEvent) e).consume();
    }
  }
}
View in GitHub: Java, Kotlin

解説

  • 上: setEnabled(false)
    • JTabbedPane#setEnabled(false)で、すべてのタブの切替を禁止
      • 内部タブコンポーネントには影響しない
      • nextボタンでJTabbedPane#setSelectedIndex(...)メソッドを使用してタブを切り替えることは可能
    • JTabbedPane#setFocusable(false)を設定している場合でも、WindowsLookAndFeelではマウスカーソルのあるタブがハイライトされる
  • 中: setTabComponentAt(...)
    • 上のサンプルと同様にJTabbedPane#setEnabled(false)で、すべてのタブの切替を禁止
    • JTabbedPane#setTabComponentAt(idx, new JLabel(title))で、タブタイトルコンポーネントをJLabelに置き換え、使用不可になっているタブタイトルの文字色を使用可の状態に戻す
  • 下: DisableInputLayerUI()
    • JTabbedPaneにマウスイベントやキー入力イベントをすべて消費するLayerUIを設定して、すべてのタブの切替を禁止
    • LayerUI#eventDispatched(...)メソッドをオーバーライドして、すべてのInputEventを消費すると、内部タブコンポーネント(このサンプルではJTextField)も入力不可になるので、JLayerを設定したJTabbedPaneの場合のみイベントを消費する用設定
      @Override
      public void eventDispatched(AWTEvent e, JLayer<? extends Component> l) {
        if (e instanceof InputEvent && Objects.equals(l.getView(), e.getSource())) {
          ((InputEvent) e).consume();
        }
      }
      

参考リンク

コメント