2016-07-13 9 views
2

Мне нужно добавить ярлык в начало JPopupMenu, который содержит другие JMenuItem s. Все идет нормально. Проблема возникает из-за того, что у моей метки есть значок с левой стороны, как «нормальный» JMenuItem, но другие элементы не будут следовать выравниванию меток, как это делается с JMenuItem. Как это:JLabel с иконкой в ​​JPopupMenu не следует за другим выравниванием JMenuItem

JPopupMenu with JMenuItem and icon

Первый элемент является JMenuItem с иконкой. Обратите внимание, что все остальные JMenuItem будут следовать выравниванию текста одного с более широким значком.

Теперь, если добавить JLabel с иконкой на JPopupMenu, эффект не будет таким же:

JPopupMenu with JLabel and icon

Или еще хуже, если добавить JLabel, не значок в JPopupMenu, который содержит другие JMenuItem с с иконками, метка не будет следовать выравниванию других и будет оставаться на одной линии слева:

JPopupMenu with JLabel and JMenuItem with icon

Мой вопрос: возможно ли установить выравнивание JLabel (значок и текст) на выравнивание JMenuItem s в JPopupMenu? Если да, то как?

ответ

2
  • Может быть отключен JMenuItem вместо JLabel.
  • EDIT: WindowsLookAndFeel работает только хорошо.
import java.awt.*; 
import java.awt.event.*; 
import javax.swing.*; 

public final class MenuItemAlignmentTest2 { 
    public JComponent makeUI() { 
    JTextArea textArea = new JTextArea(); 
    textArea.setComponentPopupMenu(makeTestPopupMenu(null)); 

    JTree tree = new JTree(); 
    tree.setComponentPopupMenu(makeTestPopupMenu(new ColorIcon(Color.RED))); 

    JPanel p = new JPanel(new GridLayout(1, 2)); 
    p.add(new JScrollPane(textArea)); 
    p.add(new JScrollPane(tree)); 
    return p; 
    } 
    private static JPopupMenu makeTestPopupMenu(Icon icon) { 
    //UIManager.put("MenuItem.disabledAreNavigable", Boolean.FALSE); 
    //UIManager.put("MenuItem.disabledForeground", Color.RED); 
    JMenuItem item0 = new JMenuItem("JMenuItem.setEnabled(false);"); 
    item0.setEnabled(false); 

    JLabel item1 = new JLabel("JLabel"); 

    JPanel item2 = new JPanel(new BorderLayout()); 
    item2.setOpaque(false); //<----------------------------- add this line 
    item2.add(new JMenuItem("JPanel with JMenuItem") { 
     @Override public boolean contains(int x, int y) { 
     return false; //disable mouse events 
     } 
    }); 

    JMenuItem item3 = new JMenuItem(" "); 
    item3.setBorder(BorderFactory.createEmptyBorder()); //<- add this line 
    item3.setEnabled(false); 
    item3.add(new JMenuItem("JMenuItem(disabled) with JMenuItem") { 
     @Override public boolean contains(int x, int y) { 
     return false; //disable mouse events 
     } 
    }); 

    JPopupMenu popup = new JPopupMenu(); 
    popup.add(makeTestMenuItems("Test0", item0, icon)); 
    popup.add(makeTestMenuItems("Test1", item1, icon)); 
    popup.add(makeTestMenuItems("Test2", item2, icon)); 
    popup.add(makeTestMenuItems("Test3", item3, icon)); 

    return popup; 
    } 
    private static JMenu makeTestMenuItems(String title, JComponent item, Icon icon) { 
    JMenu menu = new JMenu(title); 
    menu.add(item); 
    menu.addSeparator(); 
    menu.add(new AbstractAction("JMenuItem") { 
     @Override public void actionPerformed(ActionEvent e) { 
     System.out.println("actionPerformed"); 
     } 
    }); 
    menu.add("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); 
    menu.add(new JMenuItem("bbbbb", icon)); 
    return menu; 
    } 
    public static void main(String... args) { 
    EventQueue.invokeLater(() -> { 
     try { 
     UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
     } catch (ClassNotFoundException | InstantiationException 
     | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
     ex.printStackTrace(); 
     } 
     JFrame f = new JFrame(); 
     f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 

     JMenuBar mb = new JMenuBar(); 
     mb.add(LookAndFeelUtil.createLookAndFeelMenu()); 
     f.setJMenuBar(mb); 

     f.getContentPane().add(new MenuItemAlignmentTest2().makeUI()); 
     f.setSize(320, 240); 
     f.setLocationRelativeTo(null); 
     f.setVisible(true); 
    }); 
    } 
} 

final class LookAndFeelUtil { 
    private static String lookAndFeel = UIManager.getLookAndFeel().getClass().getName(); 
    public static JMenu createLookAndFeelMenu() { 
    JMenu menu = new JMenu("LookAndFeel"); 
    ButtonGroup lookAndFeelRadioGroup = new ButtonGroup(); 
    for (UIManager.LookAndFeelInfo lafInfo : UIManager.getInstalledLookAndFeels()) { 
     menu.add(createLookAndFeelItem(
      lafInfo.getName(), lafInfo.getClassName(), lookAndFeelRadioGroup)); 
    } 
    return menu; 
    } 
    private static JRadioButtonMenuItem createLookAndFeelItem(
     String lafName, String lafClassName, ButtonGroup lookAndFeelRadioGroup) { 
    JRadioButtonMenuItem lafItem = new JRadioButtonMenuItem(); 
    lafItem.setSelected(lafClassName.equals(lookAndFeel)); 
    lafItem.setHideActionText(true); 
    lafItem.setAction(new AbstractAction() { 
     @Override public void actionPerformed(ActionEvent e) { 
     ButtonModel m = lookAndFeelRadioGroup.getSelection(); 
     try { 
      setLookAndFeel(m.getActionCommand()); 
     } catch (ClassNotFoundException | InstantiationException 
        | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
      ex.printStackTrace(); 
     } 
     } 
    }); 
    lafItem.setText(lafName); 
    lafItem.setActionCommand(lafClassName); 
    lookAndFeelRadioGroup.add(lafItem); 
    return lafItem; 
    } 
    private static void setLookAndFeel(String lookAndFeel) 
     throws ClassNotFoundException, InstantiationException, 
      IllegalAccessException, UnsupportedLookAndFeelException { 
    String oldLookAndFeel = LookAndFeelUtil.lookAndFeel; 
    if (!oldLookAndFeel.equals(lookAndFeel)) { 
     UIManager.setLookAndFeel(lookAndFeel); 
     LookAndFeelUtil.lookAndFeel = lookAndFeel; 
     updateLookAndFeel(); 
     //firePropertyChange("lookAndFeel", oldLookAndFeel, lookAndFeel); 
    } 
    } 
    private static void updateLookAndFeel() { 
    for (Window window : Frame.getWindows()) { 
     SwingUtilities.updateComponentTreeUI(window); 
    } 
    } 
} 

class ColorIcon implements Icon { 
    private final Color color; 
    protected ColorIcon(Color color) { 
    this.color = color; 
    } 
    @Override public void paintIcon(Component c, Graphics g, int x, int y) { 
    Graphics2D g2 = (Graphics2D) g.create(); 
    g2.translate(x, y); 
    g2.setPaint(color); 
    g2.fillRect(1, 1, getIconWidth() - 2, getIconHeight() - 2); 
    g2.dispose(); 
    } 
    @Override public int getIconWidth() { 
    return 12; 
    } 
    @Override public int getIconHeight() { 
    return 12; 
    } 
} 
+0

Я стараюсь избегать такого подхода, потому что L & F зависит. Опция, которую вы предоставили, чтобы связать JMenuItem с JPanel, отлично работает с WindowsLookAndFeel, но с Nimbus он не работает. Хотя я считаю, что следующее не является хорошим подходом, я мог бы просто отключить JMenuItem и установить его передний план, но фон (MenuItem.disabledForeground) является глобальным, и я хочу, чтобы это изменилось только для определенного JPopupMenu в моей системе. –

+0

Спасибо за тестирование. Я обновил этот пример, но, похоже, пока не является хорошим решением. – aterai

+0

Благодарим вас за ответ. В любом случае, вы правы, новое решение по-прежнему не соответствует моим потребностям. –

 Смежные вопросы

  • Нет связанных вопросов^_^