概要

JTabbedPaneをスクロールタブレイアウトポリシーにしたとき、すべてのタブが非表示になる状態を回避するための方法をテストしています。

サンプルコード

JTabbedPane tabs = new JTabbedPane() {
  @Override public void removeTabAt(int index) {
    if (getTabCount() > 0) {
      setSelectedIndex(0);
      super.removeTabAt(index);
      setSelectedIndex(index - 1);
    } else {
      super.removeTabAt(index);
    }
  }
};
tabs.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
tabs.addTab("00000000", new JLabel("0"));
tabs.addTab("11111111", new JLabel("1"));
tabs.addTab("22222222", new JLabel("2"));
tabs.addTab("33333333", new JLabel("3"));
tabs.addTab("44444444", new JLabel("4"));
tabs.addTab("55555555", new JLabel("5"));
tabs.addTab("66666666", new JLabel("6"));
tabs.addTab("77777777", new JLabel("7"));
tabs.addTab("88888888", new JLabel("8"));
tabs.addTab("99999999", new JLabel("9"));
// TEST: tabs.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
tabs.setSelectedIndex(tabs.getTabCount() - 1);
// TEST: tabs.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
// // TEST:
// EventQueue.invokeLater(() -> {
//   tabs.setSelectedIndex(tabs.getTabCount() - 1);
//   // tabs.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
// });
View in GitHub: Java, Kotlin

解説

  • 上段
    • JTabbedPane.SCROLL_TAB_LAYOUTを設定したJTabbedPane
    • JTabbedPaneを表示状態である親コンポーネントに配置していない状態で末尾のタブを選択状態に設定しているため、このサンプルでは9のタブのみが表示されている
      • EventQueue.invokeLater(...)などを使用してすでに表示された親コンポーネントに配置された後でJTabbedPane#setSelectedIndex(...)を使用すれば回避可能
      • その場合は5から9のタブが表示状態になる
    • タブを追加した後でJTabbedPane#setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT)に変更すると0から4のタブが表示状態になる
      • ただしその後にtabs.setSelectedIndex(tabs.getTabCount() - 1)で末尾のタブを選択すると9のタブのみが表示状態になる
    • 9のタブのみが表示されている状態でその末尾の9のタブを削除すると、すべてのタブが非表示状態になる
  • 中段
    • JTabbedPane#removeTabAt(...)をオーバーライドし、タブの削除前に一旦先頭タブを選択、タブ削除、末尾タブを選択するとこで上記のようなすべてのタブが非表示状態になることを回避
      • 非表示状態のタブをTabbedPane.setSelectedIndex(...)で選択しても表示状態にならない?
    • WindowsLookAndFeelで末尾タブが選択されると上記のスクリーンショットのようにタブ右端がスクロールボタンに掛かって途切れたような表示になる場合がある
      • MetalLookAndFeelなどでは発生しない
  • 下段
    • JTabbedPane#removeTabAt(...)をオーバーライドし、タブの削除前に一旦先頭タブまでスクロール、タブ削除、末尾タブまでスクロールするとこで上記のようなすべてのタブが非表示状態になることを回避
    • スクロールしているだけなので、タブの選択状態は変化しない
    • スクロールは、コンポーネント名がTabbedPane.scrollableViewport(...)JViewportを取得してJComponent#scrollRectToVisible(...)メソッドを使用

参考リンク

コメント