【问题标题】:How change the color arrowIcon to JMenu when it is selected选择时如何将颜色箭头图标更改为 JMenu
【发布时间】:2019-10-02 18:36:53
【问题描述】:

JMenu 的箭头图标有问题:当我将鼠标悬停在它上面时,它会失去我为其设置的颜色。

这是最小的例子

public class DemoLookAndFeel extends JFrame {

    private JMenuBar menuBar = new JMenuBar();
    private JMenu arrowMenuOne = new JMenu("Root Menu 1");
    private JMenu arrowMenuTwo = new JMenu("Root Menu 2");

    static {
        UIManager.put("MenuItem.selectionForeground", Color.MAGENTA);
        UIManager.put("MenuItem.foreground",  Color.MAGENTA);
        UIManager.put("Menu.selectionForeground", Color.MAGENTA);
        UIManager.put("Menu.foreground",  Color.MAGENTA);
    }

    public void init() {

        setJMenuBar(menuBar);

        addSubMenus(arrowMenuOne, 5);
        addSubMenus(arrowMenuTwo, 3);

        menuBar.add(arrowMenuOne);
        menuBar.add(arrowMenuTwo);

        this.setSize(800,800);
        this.pack();
        this.setLocationRelativeTo(null);
        this.setVisible(true);
    }

    public void addSubMenus(JMenu parent, int number) {
        for (int i = 1; i <= number; i++) {
            JMenu menu = new JMenu("Sub Menu " + i);
            parent.add(menu);

            addSubMenus(menu, number - 1);
            addMenuItems(menu, number);
        }
    }

    public void addMenuItems(JMenu parent, int number) {
        for (int i = 1; i <= number; i++) {
            parent.add(new JMenuItem("Item " + i));
        }
    }


    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                DemoLookAndFeel demo = new DemoLookAndFeel();
                demo.init();
            }
        });
    }

}

请注意,此代码的某些部分取自堆栈溢出的其他答案。

我知道图标是用 BasiMenuUI 中的这段代码绘制的,但我仍然不明白为什么我没有得到想要的行为。

private void paintArrowIcon(Graphics g, MenuItemLayoutHelper lh,
                                MenuItemLayoutHelper.LayoutResult lr,
                                Color foreground) {
        if (lh.getArrowIcon() != null) {
            ButtonModel model = lh.getMenuItem().getModel();
            if (model.isArmed() || (lh.getMenuItem() instanceof JMenu
                                && model.isSelected())) {
                g.setColor(foreground);
            }
            if (lh.useCheckAndArrow()) {
                lh.getArrowIcon().paintIcon(lh.getMenuItem(), g,
                        lr.getArrowRect().x, lr.getArrowRect().y);
            }
        }
    }

你能帮帮我吗?谢谢

【问题讨论】:

    标签: java swing look-and-feel jmenu jmenuitem


    【解决方案1】:

    当我将鼠标悬停在它上面时,它会失去我为它设置的颜色。

    这是因为MetalLookAndFeel 中的MetalTheme 忽略了BasicLookAndFeel 的颜色设置,如下所示。

    /* @see javax/swing/plaf/metal/MetalIconFactory.java */
    class MenuArrowIcon implements Icon {
      @Override public void paintIcon(Component c, Graphics g, int x, int y) {
        JMenuItem b = (JMenuItem) c;
        ButtonModel model = b.getModel();
    
        g.translate(x, y);
        if (!model.isEnabled()) {
          g.setColor(MetalLookAndFeel.getMenuDisabledForeground());
        } else {
          if (model.isArmed() || (c instanceof JMenu && model.isSelected())) {
            g.setColor(MetalLookAndFeel.getMenuSelectedForeground());
            // use Color.MAGENTA: g.setColor(UIManager.getColor("Menu.selectedForeground"));
          } else {
            g.setColor(b.getForeground());
          }
        }
        // if (MetalUtils.isLeftToRight(b)) {
          int[] xPoints = {0, 3, 3, 0};
          int[] yPoints = {0, 3, 4, 7};
          g.fillPolygon(xPoints, yPoints, 4);
          g.drawPolygon(xPoints, yPoints, 4);
        // } else {
        //   int[] xPoints = {4, 4, 1, 1};
        //   int[] yPoints = {0, 7, 4, 3};
        //   g.fillPolygon(xPoints, yPoints, 4);
        //   g.drawPolygon(xPoints, yPoints, 4);
        // }
        g.translate(-x, -y);
      }
    
      @Override public int getIconWidth() {
        return 4;
      }
    
      @Override public int getIconHeight() {
        return 8;
      }
    }
    

    要更改菜单箭头图标的选择前景色,您可能需要更改MetalTheme 或设置自己的MenuArrowIcon

    import java.awt.*;
    import javax.swing.*;
    import javax.swing.plaf.*;
    import javax.swing.plaf.metal.*;
    
    public class DemoLookAndFeel2 extends JFrame {
      private JMenuBar menuBar = new JMenuBar();
      private JMenu arrowMenuOne = new JMenu("Root Menu 1");
      private JMenu arrowMenuTwo = new JMenu("Root Menu 2");
    
      static {
        UIManager.put("MenuItem.selectionForeground", Color.MAGENTA);
        UIManager.put("MenuItem.foreground", Color.MAGENTA);
        UIManager.put("Menu.selectionForeground", Color.MAGENTA);
        UIManager.put("Menu.foreground", Color.MAGENTA);
        // or: UIManager.put("Menu.arrowIcon", new MenuArrowIcon());
      }
    
      public void init() {
        setJMenuBar(menuBar);
        addSubMenus(arrowMenuOne, 5);
        addSubMenus(arrowMenuTwo, 3);
    
        menuBar.add(arrowMenuOne);
        menuBar.add(arrowMenuTwo);
    
        this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        this.setSize(800, 800);
        // this.pack();
        this.setLocationRelativeTo(null);
        this.setVisible(true);
      }
    
      public void addSubMenus(JMenu parent, int number) {
        for (int i = 1; i <= number; i++) {
          JMenu menu = new JMenu("Sub Menu " + i);
          parent.add(menu);
    
          addSubMenus(menu, number - 1);
          addMenuItems(menu, number);
        }
      }
    
      public void addMenuItems(JMenu parent, int number) {
        for (int i = 1; i <= number; i++) {
          parent.add(new JMenuItem("Item " + i));
        }
      }
    
      public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
          @Override public void run() {
            MetalLookAndFeel.setCurrentTheme(new DefaultMetalTheme() {
              @Override public ColorUIResource getMenuSelectedForeground() {
                return new ColorUIResource(Color.MAGENTA);
              };
            });
            DemoLookAndFeel2 demo = new DemoLookAndFeel2();
            demo.init();
          }
        });
      }
    }
    

    【讨论】:

    • 非常感谢您的澄清
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-11-06
    • 2022-08-19
    • 2021-07-31
    • 1970-01-01
    • 1970-01-01
    • 2020-09-15
    • 1970-01-01
    相关资源
    最近更新 更多