Swing GUI 在 Mac 上启动时不显示或显示错误

问题描述 投票:0回答:2

我有一个 Java Swing 项目,它在 Windows 和 Ubuntu 上都运行良好。我没有 Mac,所以无法测试;我使用 Nimbus 主题作为该项目的标准。

最近我的朋友在 Eclipse 和导出的 jar 中测试了同一个项目,它给出的错误并不涉及我所做的任何特定 Java 类。

它确实显示了 GUI,但有时会卡住,有时菜单会丢失。

这是启动 GUI 时显示的错误的精简版本:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
    at com.apple.laf.AquaMenuPainter.paintMenuBarBackground(AquaMenuPainter.java:123)
    at com.apple.laf.AquaMenuUI.paintBackground(AquaMenuUI.java:57)
    at com.apple.laf.AquaMenuPainter.paintMenuItem(AquaMenuPainter.java:160)
    at com.apple.laf.AquaMenuUI.paintMenuItem(AquaMenuUI.java:35)
    at javax.swing.plaf.basic.BasicMenuItemUI.paint(BasicMenuItemUI.java:452)
    at javax.swing.plaf.basic.BasicMenuItemUI.update(BasicMenuItemUI.java:448)
    at javax.swing.JComponent.paintComponent(JComponent.java:752)
    at javax.swing.JComponent.paint(JComponent.java:1029)
    at javax.swing.JComponent.paintChildren(JComponent.java:862)
    at javax.swing.JComponent.paint(JComponent.java:1038)
    at javax.swing.JComponent.paintChildren(JComponent.java:862)
    at javax.swing.JComponent.paint(JComponent.java:1038)
    at javax.swing.JLayeredPane.paint(JLayeredPane.java:567)
    at javax.swing.JComponent.paintChildren(JComponent.java:862)
    at javax.swing.JComponent.paint(JComponent.java:1038)
    at java.awt.GraphicsCallback$PaintCallback.run(GraphicsCallback.java:34)
    at sun.awt.SunGraphicsCallback.runOneComponent(SunGraphicsCallback.java:60)
    at sun.awt.SunGraphicsCallback.runComponents(SunGraphicsCallback.java:97)  

您能告诉我可能是什么问题,或者我应该在 Mac 上使用任何特定的外观主题吗? Mac 是否不支持 Nimbus?如果支持,我应该使用什么?

java macos swing look-and-feel nimbus
2个回答
7
投票

我不会碰 OS X 中的主题,它自动就很棒了 :D

请确保在 Mac 上时不要更改主题。

String osName = System.getProperty("os.name").toLowerCase();
if (!osName.contains("mac")) // if not on mac
{
   // set nimbus
}
// otherwise, do nothing. It goes automatically to Aqua.

0
投票

很难相信,但我昨天碰上了这堵墙,十多年后了。同一方法内的类似异常。就我而言,当尝试显示恰好在 MAC OSX 上设置了

JDialog
JMenuBar
时,就会发生这种情况。这
JMenuBar
是问题的根本原因。

我们正在使用自定义的深色主题 L&F(Bulenkov 的 Darcula),它(如果我没记错的话)基于 MAC 上的 Aqua。您可以在 Netbeans 中拥有相同的 L&F,这就是为什么您会遇到诸如this one之类的问题。

就我而言,

UIManager
中缺少
"MenuBar.backgroundPainter"
"MenuBar.selectedBackgroundPainter"
的属性。两者都应该被设置为边界实例。发生 NPE 的源代码看起来像 this:

    static class RecyclableBorder extends RecyclableSingleton<Border> {
        final String borderName;
        RecyclableBorder(final String borderName) { this.borderName = borderName; }
        protected Border getInstance() { return UIManager.getBorder(borderName); }
    }

    private static final RecyclableBorder menuBarPainter = new RecyclableBorder("MenuBar.backgroundPainter");
    private static final RecyclableBorder selectedMenuBarItemPainter = new RecyclableBorder("MenuBar.selectedBackgroundPainter");
    private static final RecyclableBorder selectedMenuItemPainter = new RecyclableBorder("MenuItem.selectedBackgroundPainter");

    public void paintMenuBarBackground(final Graphics g, final int width, final int height, final JComponent c) {
        g.setColor(c == null ? Color.white : c.getBackground());
        g.fillRect(0, 0, width, height);
        menuBarPainter.get().paintBorder(null, g, 0, 0, width, height); // NPE on .get()
    }

因此,有条件地为 MAC OSX 和深色主题设置这两个属性可以解决这个问题。

UIManager.put("MenuBar.backgroundPainter", BorderFactory.createEmptyBorder());
UIManager.put("MenuBar.selectedBackgroundPainter", BorderFactory.createEmptyBorder());

问题是,您不应该在 MAC 上拥有

JMenuBar
实例。不是画在
Window
内的那些。您应该通过
System.setProperty("apple.laf.useScreenMenuBar", "true")
移动它们,如此处所示。不幸的是,尽管使用了
JDialogs
,但这似乎仅对
JFrames
JDialog.setJMenuBar(JMenuBar)
不起作用。

© www.soinside.com 2019 - 2024. All rights reserved.