概要

JDesktopPaneJTabbedPaneCardLayoutで切り替えるとき、その内部のJInternalFrameとタブもすべて入れ替えます。

サンプルコード

Action swapAction = new AbstractAction("JDesktopPane <-> JTabbedPane") {
  @Override public void actionPerformed(ActionEvent e) {
    if (((AbstractButton) e.getSource()).isSelected()) {
      Arrays.stream(desktopPane.getAllFrames())
        .sorted(Comparator.comparing(JInternalFrame::getTitle))
        .forEach(f -> tabbedPane.addTab(f.getTitle(), f.getFrameIcon(), f.getContentPane()));

      JInternalFrame sf = desktopPane.getSelectedFrame();
      if (Objects.nonNull(sf)) {
        tabbedPane.setSelectedIndex(tabbedPane.indexOfTab(sf.getTitle()));
      }
      cardLayout.show(panel, tabbedPane.getClass().getName());
    } else {
      Arrays.stream(desktopPane.getAllFrames())
        .forEach(f -> f.setContentPane(
          (Container) tabbedPane.getComponentAt(tabbedPane.indexOfTab(f.getTitle()))));
      cardLayout.show(panel, desktopPane.getClass().getName());
    }
  }
};
View in GitHub: Java, Kotlin

解説

  • JInternalFrameJTabbedPaneのタブに変換する
    • JDesktopPane#getAllFrames()で取得した順番はJInternalFrameがアイコン化されているなどの状態で変化するので、タイトルでソートしてからJTabbedPaneに追加
    • JInternalFrame自体はそのままでContentPaneのみタブコンポーネントに変換する
    • 選択状態のJInternalFrameJDesktopPane#getSelectedFrame()メソッドで検索し、変換先のタブも選択状態になるようJTabbedPane#setSelectedIndex(...)メソッドで設定する
  • JTabbedPaneのタブをJInternalFrameに変換する
    • JDesktopPaneには、位置やサイズ、アイコン化状態などを保存した状態でJInternalFrameが残っている
      • JTabbedPane側ではタブの削除を許可していない
    • JInternalFrameのタイトルと同じタブのインデックスをJTabbedPane#indexOfTab(String)メソッドで検索し、そのコンポーネントをContentPaneとしてJInternalFrameに戻す

参考リンク

コメント