概要

JRootPaneの子コンポーネントを検索してSystemMenuとして使用されているJMenuを取得します。

サンプルコード

JTextArea log = new JTextArea();
EventQueue.invokeLater(() -> {
  JMenu menu = descendants(getRootPane())
      .filter(JMenu.class::isInstance).map(JMenu.class::cast)
      .findFirst().orElse(new JMenu(" "));
  menu.add("added to the SystemMenu");

  log.append(menu.getPreferredSize() + "\n");
  menu.setIcon(UIManager.getIcon("InternalFrame.icon"));
  log.append(menu.getPreferredSize() + "\n---\n");

  Component c = menu;
  while (c != null) {
    log.append(c.getClass().getName() + "\n");
    c = c.getParent();
  }
});
View in GitHub: Java, Kotlin

解説

  • OS依存のSystemLookAndFeelではSystemMenuJNIなどを使用しないと取得不可能
  • JFrame.setDefaultLookAndFeelDecorated(true)DefaultLookAndFeelを使用する場合、SystemMenuは以下のようなコンポーネント階層を辿って取得可能
    javax.swing.JFrame
    └─javax.swing.JRootPane
        └─javax.swing.JLayeredPane
            └─javax.swing.plaf.metal.MetalTitlePane
                └─javax.swing.plaf.metal.MetalTitlePane$SystemMenuBar
                    └─javax.swing.JMenu
    
  • 取得したJMenuのサイズが小さく、システムアイコンを右クリックしてもシステムメニューがポップアップできない場合がある
    • 上記のサンプルではシステムアイコンを再設定してクリック可能な領域を拡大している

参考リンク

コメント