• category: swing folder: MenuItemTextAlignment title: JMenuに追加したJMenuItemなどのテキスト位置を揃える tags: [JMenuBar, JMenu, JMenuItem, LookAndFeel] author: aterai pubdate: 2016-07-18T01:53:49+09:00 description: JMenuに追加したJMenuItemやJLabelなどのコンポーネントのテキスト位置を揃えて表示します。 image: https://lh3.googleusercontent.com/-S49YgtIvzc8/V4upKl0JAFI/AAAAAAAAOd4/9vWtFW4DvY4xR0bL0sM9iGRBvHz_u7AcQCCo/s800/MenuItemTextAlignment.png

概要

JMenuに追加したJMenuItemJLabelなどのコンポーネントのテキスト位置を揃えて表示します。

サンプルコード

// U+200B zero width space
JMenuItem item3 = new JMenuItem("\u200B"); //, HSTRUT);
// item3.setLayout(new BorderLayout());
// item3.setBorder(BorderFactory.createEmptyBorder()); // NimbusLookAndFeel
item3.setEnabled(false);
// item3.setDisabledIcon(HSTRUT);
item3.add(new JMenuItem("JMenuItem(disabled) with JMenuItem", HSTRUT) {
  @Override public boolean contains(int x, int y) {
    return false; //disable mouse events
  }
});
View in GitHub: Java, Kotlin

解説

JMenuJPopupMenuにクリック不可の項目としてJMenuItemの代わりにJLabelを追加すると、WindowsLookAndFeelを使用している場合や他のJMenuItemにアイコンが設定されている場合に、テキストの開始位置が揃わないので、これを回避するために以下の方法をテストしています。

  • JMenuItem.setEnabled(false);
    • JMenuItem.setEnabled(false);UIManager.put("MenuItem.disabledForeground", Color.BLACK);を使用
    • MenuItem.disabledForegroundが使用されるかどうかはLookAndFeelに依存
  • JLabel + EmptyBorder
    • 余白を設定したJLabelを使用
    • 余白の幅はLookAndFeelに依存(LookAndFeel依存の幅を取得する方法がない?)
  • JPanel with JMenuItem
    • MenuElementではない透明なJPanelに、JComponent#contains()メソッドをオーバーライドしてマウスクリックを無効にしたJMenuItemを追加
  • JMenuItem(disabled) with JMenuItem
    • JMenuItem.setEnabled(false);とした空のJMenuItemに、JComponent#contains()メソッドをオーバーライドしてマウスクリックを無効にしたJMenuItemを追加

メモ:

  • JMenuにアイコン用の余白がないMetalLookAndFeelなどにアイコンが設定されたJMenuItemが存在する場合、幅のみのアイコンを設定する必要がある
  • MetalLookAndFeelの場合、文字列もアイコンも存在しないJMenuItemは他のJMenuItemと高さが異なる(幅ゼロ空白文字\u200Bで回避)
  • NimbusLookAndFeelJPanelは、デフォルトでは背景が不透明

参考リンク

コメント