如何让密码框获得焦点?

5
这可能看起来很琐碎,但我无法弄清楚如何让此对话框中的密码框获得焦点。
import javax.swing.JOptionPane;
import javax.swing.JPasswordField;

public class PasswordBox {
    @SuppressWarnings("unused")
    public String prompt() {
        JPasswordField pass = new JPasswordField(10);
        int action = JOptionPane.showConfirmDialog(null, pass,"Enter Password",JOptionPane.OK_CANCEL_OPTION); 
        return new String(pass.getPassword());
    }
}

我可以这样从其他类中调用它:String tmpPASS = new PasswordBox().prompt();

但出现了一个问题,当对话框弹出时,“确定”按钮会获得焦点。

堆栈跟踪(请参见Eng.Fouad的答案):

at javax.swing.JComponent.addNotify(Unknown Source)
at PasswordBox$1.addNotify(PasswordBox.java:14)
at java.awt.Container.addNotify(Unknown Source)

https://dev59.com/d2025IYBdhLWcg3wCxRN#21426340 - Frank M.
4个回答

7

请查看Dialog Focus中提出的解决方案。

编辑:

使用Eng Fouad建议的方法,我认为代码应该是:

JPasswordField pass = new JPasswordField(10)         
{
    public void addNotify()             
    {                 
        super.addNotify();
        requestFocusInWindow();             
    }         
}; 

编辑2:

“Dialog Focus”博客文章中的链接有一条评论,提供了在Linux上适用的建议。


我尝试了使用AncestorListener的解决方案。不幸的是,回调根本没有被调用,所以代码无法工作。问题出在哪里? - AlexR
我已经在XP上的JDK6_7上进行了测试。也许这是一个版本/平台问题?其中一条评论建议使用HierarchyListener。尝试一下,看看会发生什么。 - camickr
Dialog Focus链接中提供的解决方案对我很有用! :) - Shervin Asgari
2
请使用他在此答案顶部的“对话框焦点”链接,这对我很有效。 - Richard

1
import javax.swing.JOptionPane;
import javax.swing.JPasswordField;

public JOptionPane pane;

public class PasswordBox
{
    @SuppressWarnings("unused")
    public String prompt()
    {
        pane = new JOptionPane();
        JPasswordField pass = new JPasswordField(10)
        {
            public void addNotify()
            {
                pane.addNotify();
                requestFocus();
            }
        };
        int action = pane.showConfirmDialog(null, pass,"Enter Password",JOptionPane.OK_CANCEL_OPTION);
        return new String(pass.getPassword());
     }
}

或者这里有另一种方法:

JPanel panel = new JPanel();
JPasswordField pass = new JPasswordField(10)
{
    public void addNotify()
    {
        panel.addNotify();
        requestFocus();
    }
};
panel.add(pass);
JOptionPane pane = new JOptionPane();
JButton btnOK = new JButton("OK");
JButton btnCancel = new JButton("Cancel");
Object[] options = {btnOK, btnCancel};
pane.showOptionDialog(null, panel, "Enter the password", JOptionPane.DEFAULT_OPTION, JOptionPane.PLAIN_MESSAGE, null, options, null);

编辑(由camickr,如果不正确请随意删除)。我认为代码应该是:

JPasswordField pass = new JPasswordField(10)         
{
    public void addNotify()             
    {                 
        super.addNotify();
        requestFocusInWindow();             
    }         
}; 

不得不在pane的声明中添加“final”,但它仍然无法工作。尽管如此,感谢您的帮助,我们非常感激 :) - user623990
@MaxMackie 不需要使用 final,只需将其作为类字段即可,参见更新 - Eng.Fouad
我仍然无法让第一个解决方案起作用,但第二个解决方案给了我一个堆栈跟踪。我会将其添加到我的问题中。 - user623990

0
问题在于JOptionPane是完全自包含的,似乎没有提供指定哪个GUI组件获得初始焦点的方法。一种解决方案是编写自己的Dialog子类-这将允许您精确控制布局并适当地设置焦点。
您还可以尝试javax.swing.SwingWorker。您可以创建一个SwingWorker,在显示密码对话框之前启动它。在doInBackground()方法中,短暂休眠,在done()方法中使用SwingUtilties.invokeLater(),并在其中Runnable中发出pass.requestFocusInWindow()。

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接