---
category: swing
folder: EditInternalFrameTitle
title: JInternalFrameにJPopupMenuを設定してタイトルを変更する
tags: [JInternalFrame, JPopupMenu]
tags: [JInternalFrame, JPopupMenu, LookAndFeel]
author: aterai
pubdate: 2021-08-30T02:48:24+09:00
description: JInternalFrameのタイトルをタイトルバーやアイコン化された状態のJDesktopIconからJPopupMenuを開いて変更します。
image: https://drive.google.com/uc?id=1OBg1GInat6Dbj4WK5tRYaSihXxU2E32R
---
* 概要 [#summary]
`JInternalFrame`のタイトルをタイトルバーやアイコン化された状態の`JDesktopIcon`から`JPopupMenu`を開いて変更します。

#download(https://drive.google.com/uc?id=1OBg1GInat6Dbj4WK5tRYaSihXxU2E32R)

* サンプルコード [#sourcecode]
#code(link){{
private static JInternalFrame createFrame(String t, int i) {
  JInternalFrame f = new JInternalFrame(t + i, true, true, true, true);
  f.setSize(200, 100);
  f.setLocation(5 + 40 * i, 5 + 50 * i);
  JPopupMenu popup = new InternalFramePopupMenu();
  f.setComponentPopupMenu(popup);
  // ((BasicInternalFrameUI) f.getUI()).getNorthPane().setComponentPopupMenu(popup);
  ((BasicInternalFrameUI) f.getUI()).getNorthPane().setInheritsPopupMenu(true);
  f.getDesktopIcon().setComponentPopupMenu(popup);
  EventQueue.invokeLater(() -> f.setVisible(true));
  return f;
}

class InternalFramePopupMenu extends JPopupMenu {
  protected InternalFramePopupMenu() {
    super();
    JTextField field = new JTextField(24); // { ... };
    String cmd = "Edit Title";
    add(cmd).addActionListener(e -> {
      Component c = getInternalFrame(getInvoker());
      if (c instanceof JInternalFrame) {
        JInternalFrame frame = (JInternalFrame) c;
        field.setText(frame.getTitle());
        Container p = frame.getDesktopPane();
        int ret = JOptionPane.showConfirmDialog(
            p, field, cmd, JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
        if (ret == JOptionPane.OK_OPTION) {
          renameInternalFrameTitle(frame, field.getText().trim());
        }
      }
    });
  }
  // ...
}

private static Component getInternalFrame(Component c) {
  Component f;
  if (c instanceof JInternalFrame.JDesktopIcon) {
    f = ((JInternalFrame.JDesktopIcon) c).getInternalFrame();
  } else if (c instanceof JInternalFrame) {
    f = c;
  } else { // if (c instanceof BasicInternalFrameTitlePane) {
    f = SwingUtilities.getAncestorOfClass(JInternalFrame.class, c);
  }
  return f;
}
}}

* 解説 [#explanation]
上記のサンプルでは、`JInternalFrame`やそのアイコン化状態でのコンポーネントである`JInternalFrame.JDesktopIcon`に`setComponentPopupMenu(...)`メソッドで`JPopupMenu`を設定し、この`JPopupMenu`から`JOptionPane`を開いて`JInternalFrame`のタイトルを変更しています。

- `Windows`環境で`JInternalFrame`のタイトルバーを右クリックした場合の動作は`LookAndFeel`で異なる
-- `NimbusLookAndFeel`
--- デフォルトでは左端のタイトル(下向き三角)アイコンをクリックしたときに表示されるシステムポップアップメニューが表示される
--- `JInternalFrame`に`JPopupMenu`を設定した場合、`SynthInternalFrameTitlePane`に設定された`JPopupMenu`を開く
--- `SynthInternalFrameTitlePane#isInheritsPopupMenu() == true`なので親`JInternalFrame`の`JPopupMenu`が開く
--- `SynthInternalFrameTitlePane`から任意(デフォルトのシステムポップアップメニューを含む)の`JPopupMenu`を開き、KBD{Esc}キーや別コンポーネントをクリックしてポップアップ表示をキャンセルすると内部的に`JInternalFrame`が移動状態が継続して再度タイトルバーを左クリックするまで`JInternalFrame`のリサイズが不可能になる(リサイズカーソルのまま`JInternalFrame`が移動する)
-- `WindowsLookAndFeel`
--- デフォルトではタイトルバーのシングル右クリックは無視され(システムメニューは表示されない)、左右どのマウスボタンのダブルクリックでも`JInternalFrame`の最大化、復元が実行される
--- デフォルトは`WindowsInternalFrameTitlePane#isInheritsPopupMenu() == true`なので、`WindowsInternalFrameTitlePane#setInheritsPopupMenu(true)`などの設定で右クリックはポップアップ表示に変更可能(右マウスボタンのダブルクリックは無効になる)

* 参考リンク [#reference]
- [[JInternalFrameのタイトル文字列幅を取得し、その値でJDesktopIconの幅を調整する>Swing/ComputeTitleWidth]]

* コメント [#comment]
#comment
#comment