4

OS X 2013-004 (Java 1.6.0_51) 的 Java 似乎破坏了一些 Swing 应用程序:https ://discussions.apple.com/message/22279872?tstart=0#22279872?tstart=0 http://www。 mathworks.com/matlabcentral/answers/79489

我的应用程序加载,但它不会正常重绘。单击按钮和其他操作实际上似乎有效,但只有在调整框架大小时才会更新显示 - 真的很奇怪。

有谁知道问题可能是什么?

编辑:似乎苹果修复了它: http: //lists.apple.com/archives/java-dev/2013/Jun/msg00055.html

4

3 回答 3

3

2013-06-21 更新:此答案包含一些可能有用的解决方法和替代方案,但@sidney-markowitz-biomatters 的答案包含正确的代码修复 - 需要从事件线程设置 LAF!

最近的问题似乎与破坏 Aqua 外观 (LAF) 的更新有关,这是 Mac OS X 上 Swing 应用程序的默认设置。

如果您需要 Aqua LAF,那么没有太多选择。您可能需要等待 Apple 的下一次 Java 更新(我假设他们会优先解决这个问题,因为这是他们自己的 LAF)。您也可以尝试使用Java Application Bundler(即捆绑 Oracle JRE 并避免使用系统的 JRE)。

如果您可以使用不同的 LAF,那么您的应用程序应该可以正常工作。至少对于PaperCut确实如此(003 更新导致一些窗口焦点问题,004 更新导致混乱)。

一些选项:

  • 从 Java 代码(例如 Nimbus 或 Metal)使用 Java版本特定的跨平台 LAF:

    UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName())
    
  • 从 Java 代码设置特定的 LAF:

    UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel")
    
  • 从终端覆盖默认 LAF:

    java -Dswing.defaultlaf=javax.swing.plaf.nimbus.NimbusLookAndFeel MyApp
    

在我们的例子中,我们UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName())在代码中显式调用,并且想要一个不涉及代码更改(即修补程序)的解决方法,因此我们需要覆盖默认系统LAF,如下所示。

  • 从终端覆盖系统 LAF:

    java -Dswing.systemlaf=javax.swing.plaf.nimbus.NimbusLookAndFeel ...
    
  • Info.plist从文件覆盖系统 LAF(如果您已捆绑为 Mac 应用程序,也适用于其他 VM 选项)(例如 at My.app/Contents/Info.plist)。

    您想要添加-Dswing.systemlaf=javax.swing.plaf.nimbus.NimbusLookAndFeel到. _ 选项是空格分隔的,就像终端一样。例如,如果您已经有一个选项:<string>VMOptions <key>useScreenMenuBar

    <key>VMOptions</key>
    <string>-Dcom.apple.macos.useScreenMenuBar=true -Dswing.systemlaf=javax.swing.plaf.nimbus.NimbusLookAndFeel</string>
    


编辑:@trashgod 要求提供可重现的示例。我不确定 004 更新问题的全部范围是什么,但这里有一个简单的复制:

更新 2013-06-21 - 错误的方式,重现错误:

public class AquaLafTest {
    public static void main(String[] args) throws Exception {
        javax.swing.UIManager.setLookAndFeel(javax.swing.UIManager.getSystemLookAndFeelClassName());
        javax.swing.JOptionPane.showMessageDialog(null, "msg");
    }
}
  1. 使用 004 更新附带的 Apple JRE(例如 at /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home)运行。观察到消息不可见,对话框图标不可见,并且按钮不可点击。

  2. 使用较旧的 Apple JRE 或其他 JRE 运行。观察对话框是否按预期显示。

更新 2013-06-21 - 在事件线程上,正确的方法可以正常工作:

public class AquaLafTest {
    public static void main(String[] args) throws Exception {
        javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
            public void run() {
                try {
                    javax.swing.UIManager.setLookAndFeel(javax.swing.UIManager.getSystemLookAndFeelClassName());
                    javax.swing.JOptionPane.showMessageDialog(null, "msg");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
}
于 2013-06-20T07:23:30.403 回答
2

您曾经能够摆脱UIManager.setLookAndFeel()从 Swing 线程外部调用的情况。通过使用该调用设置外观来启动应用程序可能很常见。Swing API 文档说,您可以从该线程外部调用的唯一 Swing 方法是在方法的 JavaDoc 中标记为线程安全的方法。setLookAndFeel没有标记thread-safe。由于它在被调用时不涉及显示任何内容并且它总是可以正常工作,我敢打赌很多人认为它是一种在实际执行任何 GUI 之前设置一些配置设置的方法,只需调用一次就忘记了关于它。

尝试以UIManager.setLookAndFeel与所有其他 Swing 方法相同的方式包装调用,以确保它在 Swing 线程(有时称为调度或 UI 线程)中运行。还要寻找在 Swing 线程之外调用的其他 Swing 方法,以防此更新使其他方法在线程安全方面更加挑剔。

[添加示例代码]

@tom-clift 在他的答案中添加了显示失败代码和正常工作代码的优秀示例。我正在更新此答案以包含他的示例片段,以显示您应该用什么替换对 setLookAndFeel 的调用。对 UIManager 方法的任何其他调用执行相同的操作,例如,如果您在其中设置特定属性。

    javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
        public void run() {
            try {
                javax.swing.UIManager.setLookAndFeel(javax.swing.UIManager.getSystemLookAndFeelClassName());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
于 2013-06-21T01:25:14.607 回答
2

此问题已通过 Apple 发布这些更新的修订版得到解决:http: //support.apple.com/kb/DL1572 (10.7, 10.8+) http://support.apple.com/kb/DL1573 (10.6-只要)

于 2013-06-21T20:02:35.260 回答