Java for OS X 2013-004如何影响(中断)Swing应用程序?

时间:2013-06-20 02:40:31

标签: java macos oracle swing

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

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

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

修改:似乎Apple修了它:http://lists.apple.com/archives/java-dev/2013/Jun/msg00055.html

3 个答案:

答案 0 :(得分:3)

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

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

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

如果您可以使用不同的LAF,那么您的应用应该正常工作。它至少为PaperCut做了(003更新引起了一些窗口焦点问题,004更新引起了混乱)。

一些选项:

  • 从Java代码(例如Nimbus或Metal)使用Java version-specific跨平台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选项)(例如My.app/Contents/Info.plist })。

    您想将-Dswing.systemlaf=javax.swing.plaf.nimbus.NimbusLookAndFeel添加到<string> VMOptions的{​​{1}}值的 end 。选项是空间分隔的,就像从终端一样。例如。如果您已经有<key>选项:

    useScreenMenuBar


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

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

<key>VMOptions</key>
<string>-Dcom.apple.macos.useScreenMenuBar=true -Dswing.systemlaf=javax.swing.plaf.nimbus.NimbusLookAndFeel</string>
  1. 使用004更新附带的Apple JRE运行(例如,在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"); } } )。观察到消息不可见,对话框图标不可见,按钮不可见。

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

  3. 更新2013-06-21 - 正确的方式,在事件线程上,正常工作:

    /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home

答案 1 :(得分:2)

您曾经能够从Swing线程外部调用UIManager.setLookAndFeel()。通过设置该调用的外观来启动应用程序可能很常见。 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();
            }
        }
    });

答案 2 :(得分:2)

Apple发布了这些更新的修订版本已解决此问题: http://support.apple.com/kb/DL1572(10.7,10.8 +) http://support.apple.com/kb/DL1573(仅限10.6)