8

我一直在验证一个在 mac osx 的小程序上运行的 swing 应用程序。

在此验证期间,我发现模态对话框存在以下问题:

  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 文件:

<html>
<head>
<title>Dialog test Applet</title>
</head>
<body>
<applet id="DialogTestApplet" height="800" width="600"
  code="com.macosx.tests.DialogExample"
  archive="test.jar">
</applet>
</div>
</body>
</html>

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

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

那么,我在这里做错了什么?请问有mac电脑的人可以测试一下吗?

谢谢

眼镜:

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

browser        firefox 15

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

4

9 回答 9

6

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

将此代码片段添加到您的对话框构造函数中,它应该可以工作:

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);
}
于 2012-12-13T14:12:40.487 回答
1

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

于 2012-09-05T09:56:47.753 回答
1

我在 Mac 上使用 Safari 和 Firefox 的 Java 7 update 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太短了。

于 2012-10-24T10:05:25.363 回答
1

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

于 2012-09-25T13:20:23.473 回答
1
  • 不是 Mac/OSX 用户,但这是关于Focusand的常见问题JDialog

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

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

  • 只创建JDialog一次,然后再re_use创建container一次

  • JDialog#setVisibleinvokeLater()也应该被包裹进去

  • 可以强制FocusbyJTextField#setText(JTextField#getText())包裹成invokeLater()

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

于 2012-09-05T11:06:07.073 回答
1

我可以验证这是 Safari 6 上的 Java 1.7 Update 7+ 和在 Mountain Lion 上运行的 Firefox 的问题。奇怪的是,在 Lion 上运行的早期版本的 Safari 上这不是问题,但在旧操作系统上的 Firefox 中却是一个问题。我非常渴望找到解决此问题的方法,因为我的许多 applet 用户都在 Mac 上。我发现的一种解决方法(无论如何都不够)是缩小窗口然后重新打开它。然后文本字段/文本区域变得可编辑。希望我们能找到一个更好的解决方案来解决这个烦人的要求。

于 2012-10-18T23:18:10.683 回答
0

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

final JDialog dialog = new JDialog();
dialog.setUndecorated(true);
dialog.setSize(0, 0);
dialog.setModal(true);
dialog.pack();
于 2013-01-14T09:27:08.187 回答
0

我发现了另一种解决方法。当从 JavaScript 调用 JDialog 时,它有一个焦点。

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

希望能帮助到你。顺便说一句,Java 教程中的 Web 启动示例有同样的问题http://docs.oracle.com/javase/tutorial/uiswing/components/textfield.html

于 2012-10-25T03:57:08.527 回答
0

我找到了解决方案。

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

GetDirectory 是包含 JFileChooser 的 JDialog。

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

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

为了把它放在首位,我已经如上所述设置了所有 JDialogs 的父级,它按照预期工作。

于 2018-03-11T08:34:52.397 回答