Swing和Nimbus:替换JPopupMenu的背景(附加到JMenu) [英] Swing and Nimbus: Replace background of JPopupMenu (attached to JMenu)

查看:97
本文介绍了Swing和Nimbus:替换JPopupMenu的背景(附加到JMenu)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Nimbus通常看起来很棒,但对于某些颜色组合,结果并非最佳。在我的情况下, JPopupMenu 的背景不合适,这就是我想手动设置的原因。

Nimbus often looks great, but for certain color combinations the result is non-optimal. In my case, the background of a JPopupMenu does not fit, which is why I want to set it manually.

我在使用Java 7,有趣的是,Nimbus完全忽略了 UIManager 中某些属性的设置(如 PopupMenu.background )。所以我唯一的选择是创建一个 JPopupMenu 的子类,它会覆盖 paintComponent(...)。我知道,这很讨厌,但至少它有效。

I'm on Java 7 and, interestingly, Nimbus fully ignores the setting of some properties in the UIManager (like PopupMenu.background). So my only option was to create a subclass of JPopupMenu that overrides paintComponent(...). I know, that's nasty, but at least it worked.

但是,如果你将 JMenu 添加到另一个菜单,它嵌入了它自己的 JPopupMenu 的实例,我无法弄清楚如何用我自己的子类替换它。

However, if you add a JMenu to another menu, it embeds it's own instance of JPopupMenu and I could not figure out how to replace it with my own subclass.

即使为嵌入式实例分配一个自己的 PopupMenuUI 也没有带来任何结果。如果直接从 JPopupMenu 继承,则调用覆盖 paint(...)方法,但不管我做了什么什么也没画。如果继承自 javax.swing.plaf.synth.SynthPopupMenuUI paint 甚至没有调用,结果是如果我根本没有设置自己的 PopupMenuUI

Even assigning an own PopupMenuUI to the embedded instance didn't bring any results. If inherited directly from JPopupMenu the overriden paint(...) method was called, but, not matter what I did, nothing was drawn. If inherited from javax.swing.plaf.synth.SynthPopupMenuUI paint isn't even called and the result is if I hadn't set an own PopupMenuUI at all.

所以简单的问题是:如何调整一个 JPopupMenu 的背景颜色或(如果这更容易)所有这些都在Java 7上使用Nimbus作为L& F?

So the simple question is: How do I adjust the background color of one JPopupMenu or (if that's easier) all of them on Java 7 using Nimbus as L&F?

编辑:代码示例

看看下面的代码和结果:

Take a look at the following code and the result:

public static void main(final String[] args) {
    try {
        UIManager.setLookAndFeel(NimbusLookAndFeel.class.getCanonicalName());
        UIManager.getLookAndFeelDefaults().put("PopupMenu.background", Color.GREEN);
        UIManager.getLookAndFeelDefaults().put("Panel.background", Color.RED);
        UIManager.getLookAndFeelDefaults().put("List.background", Color.BLUE);
    } catch (ClassNotFoundException | InstantiationException
            | IllegalAccessException | UnsupportedLookAndFeelException e) {
        e.printStackTrace();
    }
    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(200,200);

    JPanel panel = new JPanel(new BorderLayout());
    panel.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
    JList list = new JList();
    panel.add(list);

    frame.getContentPane().add(panel);

    JPopupMenu menu = new JPopupMenu();
    menu.add(new JMenuItem("A"));
    menu.add(new JMenuItem("B"));
    menu.add(new JMenuItem("C"));

    frame.setVisible(true);
    menu.show(frame, 50, 50);
}

我知道,有人说你应该使用 UIManager .put(键,值) UIManager.getLookAndFeelDefautls()。put(key,value) 设置之前L& F,但对我来说这并没有带来任何结果(意思是:根本没有改变默认颜色)。上面的代码至少带来:

I know, some say that you should use UIManager.put(key, value) or UIManager.getLookAndFeelDefautls().put(key,value) before setting the L&F, but for me this does not bring any results (meaning: no changes to the default colors at all). The code above at least brings:

如果您使用 JPopupMenu.setBackground(...),则会发生同样的事情(无意义)。这是因为Nimbus使用内部画家,它根据Nimbus的原色计算颜色并忽略组件的属性。在此示例中,您可以使用以下方法作为解决方法:

Same thing (meaning nothing) happens if you use JPopupMenu.setBackground(...). This is because Nimbus uses an internal painter, which computes the color from Nimbus' primary colors and ignores the components' property. In this example, you can use the following as workaround:

JPopupMenu menu = new JPopupMenu() {
    @Override
    public void paintComponent(final Graphics g) {
        g.setColor(Color.GREEN);
        g.fillRect(0,0,getWidth(), getHeight());
    }
};

带来

但是,如果您插入<此解决方法不起作用code> JMenu 它本身包装 JPopupMenu 你无法覆盖:

However, this workaround does not work if you insert a JMenu which itself wraps a JPopupMenu you can't override:

JMenu jmenu = new JMenu("D");
jmenu.add(new JMenuItem("E"));
menu.add(jmenu);

按预期给出:

< img src =https://i.stack.imgur.com/56PNg.pngalt =第三屏>

您可以检索此 JPopupMenu 使用 JMenu.getPopupMenu()但您无法设置它。甚至在 JMenu 的子类中重写此方法也不会带来任何结果,因为 JMenu 似乎访问它的enwrapped实例不使用getter的 JPopupMenu

You can retrieve this JPopupMenu using JMenu.getPopupMenu() but you can't set it. Even overriding this method in an own subclass of JMenu does not bring any results, as JMenu seems to access it's enwrapped instance of JPopupMenu without using the getter.

推荐答案


  • 两个答案都有一些错误

    • there are a few mistakes in both answers

      以及上面提到的覆盖大多数对另一个JComponents产生影响的UIDeafault所需的方法它的颜色

      and above mentioned way to required to override most UIDeafaults that have got impact to the another JComponents and its Color(s)

      Nimbus拥有自己的Painter,其中一个例子......

      Nimbus has own Painter, one example for that ...

      代码

      import com.sun.java.swing.Painter;
      import java.awt.*;
      import javax.swing.*;
      
      public class MyPopupWithNimbus {
      
          public MyPopupWithNimbus() {
              JFrame frame = new JFrame();
              frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
              frame.setSize(200, 200);
              JPanel panel = new JPanel(new BorderLayout());
              panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
              JList list = new JList();
              panel.add(list);
              frame.getContentPane().add(panel);
              JPopupMenu menu = new JPopupMenu();
              menu.add(new JMenuItem("A"));
              menu.add(new JMenuItem("B"));
              menu.add(new JMenuItem("C"));
              JMenu jmenu = new JMenu("D");
              jmenu.add(new JMenuItem("E"));
              menu.add(jmenu);
              frame.setVisible(true);
              menu.show(frame, 50, 50);
          }
      
          public static void main(String[] args) {
      
              try {
                  for (UIManager.LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels()) {
                      if ("Nimbus".equals(laf.getName())) {
                          UIManager.setLookAndFeel(laf.getClassName());
                          UIManager.getLookAndFeelDefaults().put("PopupMenu[Enabled].backgroundPainter",
                                  new FillPainter(new Color(127, 255, 191)));
                      }
                  }
              } catch (Exception e) {
                  e.printStackTrace();
              }
              EventQueue.invokeLater(new Runnable() {
      
                  @Override
                  public void run() {
                      MyPopupWithNimbus aa = new MyPopupWithNimbus();
                  }
              });
          }
      }
      
      class FillPainter implements Painter<JComponent> {
      
          private final Color color;
      
          FillPainter(Color c) {
              color = c;
          }
      
          @Override
          public void paint(Graphics2D g, JComponent object, int width, int height) {
              g.setColor(color);
              g.fillRect(0, 0, width - 1, height - 1);
          }
      }
      

      这篇关于Swing和Nimbus:替换JPopupMenu的背景(附加到JMenu)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆