关注mac osx上java7模式对话框的问题

我一直在validation在mac osx的applet上运行的swing应用程序。

在此validation过程中,我发现模式对话框存在以下问题:

  1. 当一个对话框打开并且是setModal(true)时,它会阻止根窗口的内容,但是如果你点击根窗口的某个地方,对话框会在它下面,但它应该保留在根窗口的顶部。
  2. 如果对话框有JTextInputField,即使单击它也不会获得焦点。

所以我创建了一个小程序来显示问题。 你能帮我理解这里有什么问题吗?

package com.macosx.tests; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.*; public class DialogExample extends JApplet{ private static final long serialVersionUID = 1L; private JPanel panel; private JButton openDialogBtn; private void doStart() { panel = new JPanel(); panel.setPreferredSize(new Dimension(500,500)); openDialogBtn = new JButton("open dialog"); openDialogBtn.addActionListener(new ActionListener(){ @Override public void actionPerformed(ActionEvent arg0) { ModalDialog dialog = new ModalDialog(panel, true); dialog.setVisible(true); } }); panel.add(openDialogBtn); setContentPane(panel); } class ModalDialog extends JDialog { private static final long serialVersionUID = 1L; public ModalDialog(Component parent, boolean modal) { Dimension dimensionParentFrame = parent.getSize(); setSize(new Dimension((parent == null) ? 300 : dimensionParentFrame.width / 2, 75)); setModal(modal); setModalityType(ModalityType.APPLICATION_MODAL); JTextField txtField = new JTextField(); add(txtField, BorderLayout.CENTER); } } @Override public void start() { try { SwingUtilities.invokeAndWait(new Runnable() { public void run() { doStart(); } }); } catch (Exception e) { throw new RuntimeException(e); } } } 

使用上面的方法创建.jar文件(test.jar)。 完成后,创建一个包含以下内容的html文件:

   Dialog test Applet     

完成后,运行html文件。 你会看到一个灰色背景和一个按钮的小程序。 然后尝试:

  1. 单击按钮打开对话框。 之后,单击灰色区域的某个位置:对话框在浏览器窗口下方,但它应保持在顶部,对吧?
  2. 单击按钮打开对话框。 之后单击对话框的文本字段并尝试编写一些内容:textdialog无法获得焦点。

那么,我在这里做错了什么? 有人用Mac电脑测试一下吗?

谢谢

眼镜:

 java.vendor Oracle Corporation java.version 1.7.0_07 os.name Mac OS X os.version 10.7.4 browser firefox 15 

注意:请注意,这仅在applet在浏览器上运行且仅在mac osx上运行时才会发生。

我发现了另一种解决方法。 打开窗口时,显示一个选项窗格几毫秒并关闭它。 它将焦点放在选项窗格上,然后返回到对话框,允许忽略该错误。

将此snipet代码添加到对话框构造函数中,它应该工作:

 addWindowListener(new WindowAdapter(){ public void windowOpened(WindowEvent e){ JOptionPane pane = new JOptionPane(); final JDialog dialog = pane.createDialog("Please Wait"); Timer timer = new Timer(50, new ActionListener() { public void actionPerformed(ActionEvent e) { dialog.dispose(); } }); timer.setRepeats(false); timer.start(); dialog.setVisible(true); } 

您应该在ModalDialog上放置一个“所有者”窗口。 为此,您必须在ModalDialog构造函数中调用super(owner),并且可以使用SwingUtilities.getWindowAncestor(parent)检索组件parent的父窗口。

  • 不是Mac / OSX用户,但这是关于FocusJDialog常见问题,

  • 在运行时创建JDialog的情况下还有另一个问题,

  • Focus是基于Native OS属性而异步的

  • 只创建一次JDialog然后re_usecontainer进行另一个操作

  • JDialog#setVisible应该包装到invokeLater()

  • 可以通过JTextField#setText(JTextField#getText())强制Focus JTextField#setText(JTextField#getText())包装到invokeLater()

  • Dialog Focus是@camickr的一个很好的解决方法

我确认,我在OS X上的JDK7中运行的旧applet也有同样的错误。正如海报所提到的,只有applet在浏览器中运行(ff)而不是appletviewer才能看到错误。

我可以validation这是Safari Mountain 6上的Java 1.7 Update 7+和Mountain Lion上运行的Firefox的问题。 奇怪的是,早期版本的Safari在Lion上运行并不是问题,但在旧操作系统的Firefox中存在问题。 由于许多applet用户都在Mac上,我非常渴望找到解决方法。 我找到的一个解决方法(通过任何方式都不够)是缩小窗口然后重新打开它。 textfields / textareas然后变得可编辑。 希望我们能找到更好的解决方案来解决这个烦人的需求。

我在Mac上使用Safari和Firefox的Java 7更新9遇到了同样的问题。 当我打开一个包含JTextField的JDialog时,JTextField无法访问。

我确实找到了解决方案。 我插入了一个延迟,从用户按下“显示对话框按钮”到执行显示按钮的代码。

例如:

 ActionListener al = new ActionListener(){ public void actionPerformed(ActionEvent ae){ TitleDialog dialog = new TitleDialog(main.findParentFrame()); // My JDialog which contains a JTextField. dialog.setVisible(true); } }; javax.swing.Timer timer = new javax.swing.Timer(1000, al); timer.setRepeats(false); timer.start(); 

我经历过,如果延迟时间很短,解决方案将无效。

如果使用SwingUtilities.invokeLater而不是javax.swing.Timer它将无法正常工作。 也许SwingUtilities.invokeLater的延迟太短了。

我找到了另外一个解决方法。 从JavaScript调用JDialog时,它有一个焦点。

  1. 创建一个applet的方法,它将显示一个对话框
  2. 从JavaScript调用此方法。

希望能帮助到你。 顺便说一下,来自Java教程的web start示例也有同样的问题http://docs.oracle.com/javase/tutorial/uiswing/components/textfield.html

我想使用上面的解决方法(从对话框打开对话框),但没有显示任何对话框。 这是一个不可见对话框的代码。

 final JDialog dialog = new JDialog(); dialog.setUndecorated(true); dialog.setSize(0, 0); dialog.setModal(true); dialog.pack(); 

我找到了解决方案。

 GetDirectory varGetDirectory = new GetDirectory(new JFrame(),true); varGetDirectory.setVisible(true); 

GetDirectory是包含JFileChooser的JDialog。

奇怪的是,所有JDialog对象都应该使用新的JFrame()作为父级进行调用,否则从一个父窗口单击将使顶级模态JDialog在zOrder中向后移动,并且不知何故它不能再设置在顶部。

我的问题和上面一样。 当我从另一个JDialog创建JDialog时,新对话框出现在另一个之后。

为了使它成为顶部我已经设置了所有JDialogs的父级,如上所述,它根据预期工作。