让JOptionPane.showConfirmDialog()在Mac OSX上运行

时间:2015-02-17 21:39:38

标签: java macos swing joptionpane

我无法获取消息框和程度对话框以在Mac中正确显示/运行(v10.9.5)。

我刚刚将JRE和JDK更新到最新版本(8u31)。终端窗口中的“java -version”显示我确实使用的是8u31。 (我之前使用的是8u20,表现出相同的行为。)

下面的代码在Windows和我测试的几个不同版本的Linux中完美运行,没有任何问题。我只是在Mac上遇到问题。我精简了我的代码,这是基于SWT的,但是这个例子使用Swing,如下所示:

package myTest;

import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

public class EntryCode
{
    public static EntryCode oEntryCode;

    public EntryCode()
    {
        // TODO Auto-generated constructor stub
    }

    public static void main(String[] args)
    {
        oEntryCode = new EntryCode();

        oEntryCode.open();
    }

    public void open()
    {
        JPanel panel = new JPanel();
        panel.setMinimumSize(new Dimension(200,200));

        JFrame frame = new JFrame("JOptionPane showMessageDialog component example");
        System.out.println("open(): entry - With frame");
        JOptionPane.showConfirmDialog(frame, "Wow, works on the Mac!", "Inside open()", JOptionPane.YES_NO_OPTION);
        System.out.println("Point 1");

        System.exit(0);
    }
}

我看到第一个系统输出行,代码挂起在消息框请求上。在实际代码中,我只使用null作为第一个参数。这个测试代码的原始版本也使用了null,只是我在试验指定一个组件。我认为这可能是问题所在。事实并非如此。

显示SWT对话框时,单击按钮会导致界面挂起。挂起位于按下按钮和事件处理程序触发之间。事件处理程序永远不会触发。

我这里没有包含对话框。我认为,由于我的确认/消息框显示了解决问题的相同问题,因此免费获取另一个。

我在Google上搜索了在Mac上显示java应用程序,但没有出现任何内容。

我认为将JRE / JDK更新到最新版本可以解决任何与操作系统相关的问题。

我将代码编译为jar并使用以下命令从终端窗口运行。我按Ctrl + C到完全挂起的应用程序。

java -XstartOnFirstThread -jar myTest.jar

思想?

更新

我删除了原始更新,但我现在离开了原始问题,现在我更好地理解了这个问题。

真正的问题是如何启动适当的Mac OSX Cocoa限制友好型SWT应用程序,该应用程序使用对话框和消息框。 (据我所知,显示消息框的唯一方法是使用JOptionPane.show *,这是一个Swing的东西,从而混合了Swing和SWT。

值得注意的是,问题始终与按钮有关,无论是在对话框(纯粹的SWT实现)还是消息框上。在前者中,问题是挂起调用事件处理程序,后者显示消息框(null第一个参数,因为SWT应用程序中不存在Swing框架。)

2 个答案:

答案 0 :(得分:2)

问题可能是您没有在EDT中启动GUI。试试这个:

public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            oEntryCode = new EntryCode();
            oEntryCode.open();
        }
    });
}

更多信息:http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html

另一个问题是将-XstartOnFirstThread与Swing一起使用。 Swing相当于-XstartOnFirstThread正在做的事情,但是以自己的方式。你不应该将-XstartOnFirstThread与Swing一起使用,因为混合SWT和Swing并不是一个好主意。

如果您添加SwingUtilities.invokeLater()并删除-XstartOnFirstThread,则您的示例应正常运行。

答案 1 :(得分:1)

不太确定这可能是错误,因为我目前无法在Mac上测试它。但是你永远不会将JFrame的可见性设置为true。将框架作为参数传递给JOptionPane时,窗格会尝试显示框架中的窗格。

所以试试:

 public void open()
{
    JFrame frame = new JFrame("JOptionPane showMessageDialog component example");
    System.out.println("open(): entry - With frame");
    frame.setSize(300,300);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);

    JOptionPane.showConfirmDialog(frame, "Wow, works on the Mac!", "Inside open()", JOptionPane.YES_NO_OPTION);
    System.out.println("Point 1");

    System.exit(0);
}

另外,为什么你创建JPanel面板从未被我用过?

由于框架不可见,这可能会导致问题。只是一个猜测...... 这也可以解释为什么你的应用程序看起来像“冻结”。这是因为它等待您在JOptionPane中进行选择,但由于您无法看到JOptionPane而无法进行选择。

我知道你写过你也试过传递null作为参数但是我认为这也可能在没有显示其他JFrame时引起问题。正如我所说的那样。试试看,然后回来提供更多信息。

修改 刚刚测试过,看起来你的代码很好。您的错误必须在您的mac或java设置中。

编辑2 我想我找到了你的答案。看起来startOnFirstThread是问题所在。我刚刚在命令行上通过javac和java进行了测试。看看这个:

  

Swing停止工作,因为-XstartOnFirstThread意味着那个
  其他人(非常可能是SWT)将会出现并开始发挥作用   使用CFRunLoop等在线程0上抽取事件循环

这可以解释为什么你的JOptionPane难以出现。 (摘自:here

也有些陈旧但描述了你的问题:

  

AWT问题通常归结为jvm启动的线程。在Mac上使用java启动程序(如pde所做)时,默认情况下java会在第二个线程(这是AWT想要的)上启动,除非您指定-XstartOnFirstThread(这是S​​WT想要的)。   (https://bugs.eclipse.org/bugs/show_bug.cgi?id=212617)