Java 如何在JOptionPane中设置默认输入字段

Java 如何在JOptionPane中设置默认输入字段,java,joptionpane,Java,Joptionpane,我有以下代码: JTextField uname = new JTextField(defaultUser); JPasswordField passwd = new JPasswordField(); JTextField serverAddress = new JTextField(defaultServer); JTextField port = new JTextField(Integer.toString(defaultPort)); final JComponent[] inputs

我有以下代码:

JTextField uname = new JTextField(defaultUser);
JPasswordField passwd = new JPasswordField();
JTextField serverAddress = new JTextField(defaultServer);
JTextField port = new JTextField(Integer.toString(defaultPort));
final JComponent[] inputs = new JComponent[]{new JLabel("Username"), uname, new JLabel("Password"), passwd, new JLabel("Server Address"), serverAddress, new JLabel("Server Port"), port};


int var = JOptionPane.showConfirmDialog(parent, inputs, "Enter Connection Details", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
if (var != 0) {
    return;
}
....
这将创建一个对话框,提示输入连接到服务器的某些详细信息。我想要的是将密码字段设置为默认选中的字段。也就是说,默认情况下,光标在那里,因此您可以在窗格出现时立即开始键入光标,而不必首先选择密码框-默认情况下,“确定”按钮具有焦点

我尝试过passwd.requestFocusInWindow(),但它不起作用(因为我认为在调用该框之前,该框必须可见才能起作用)。我还尝试用各种内容覆盖passwd的requestFocus方法,但也没有成功(可能是因为它没有被调用……)

注意:我知道其他一些JOptionPane方法有默认值参数,但它们在布局输入框时有问题,因此对我没有好处

有人有什么想法吗?这不是一个交易的破坏者,所以如果不能很容易地完成,我不会太难过


干杯

尝试将ComponentListener添加到密码字段,当它变为可见时,调用#requestFocusInWindow

更新:
JOptionPane
在对话框中默认设置[OK]按钮,并在显示对话框时将其聚焦。所以解决办法不是那么明显。。。我们必须添加一个
HierarchyListener
并等待密码字段添加到对话框中,然后检查对话框的
JRootPane
是否有默认按钮,如果有,则添加一个
FocusListener
,最后当按钮获得永久焦点时,将焦点切换到密码字段:

import static javax.swing.JOptionPane.OK_CANCEL_OPTION;
import static javax.swing.JOptionPane.PLAIN_MESSAGE;

import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.HierarchyEvent;
import java.awt.event.HierarchyListener;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPasswordField;
import javax.swing.JRootPane;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class FocusPasswordFieldInOptionPaneDemo implements Runnable
{
    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(new FocusPasswordFieldInOptionPaneDemo());
    }

    @Override
    public void run()
    {
        JTextField uname = new JTextField("user");
        JPasswordField passwd = new JPasswordField();
        JTextField serverAddress = new JTextField("server");
        JTextField port = new JTextField(Integer.toString(1337));
        final JComponent[] inputs = new JComponent[] {new JLabel("Username"), uname, new JLabel("Password"), passwd,
                new JLabel("Server Address"), serverAddress, new JLabel("Server Port"), port};

        makeSurePasswordFieldGetsFocus(passwd);

        int answer = JOptionPane.showConfirmDialog(null, inputs, "Enter Connection Details", OK_CANCEL_OPTION, PLAIN_MESSAGE);
        System.out.println(answer);
    }

    /**
     * {@link JOptionPane} makes the [OK] button default in the dialog and makes it focused.
     * <p>
     * So via a couple of listeners we can wait until the button gets permanent focus and then switch focus to the password field.
     */
    private void makeSurePasswordFieldGetsFocus(final JPasswordField passwd)
    {
        passwd.addHierarchyListener(new HierarchyListener()
        {
            HierarchyListener hierarchyListener = this;

            @Override
            public void hierarchyChanged(HierarchyEvent e)
            {
                JRootPane rootPane = SwingUtilities.getRootPane(passwd);
                if (rootPane != null)
                {
                    final JButton okButton = rootPane.getDefaultButton();
                    if (okButton != null)
                    {
                        okButton.addFocusListener(new FocusAdapter()
                        {
                            @Override
                            public void focusGained(FocusEvent e)
                            {
                                if (!e.isTemporary())
                                {
                                    passwd.requestFocusInWindow();
                                    passwd.removeHierarchyListener(hierarchyListener);
                                    okButton.removeFocusListener(this);
                                }
                            }
                        });
                    }
                }
            }
        });
    }
}
import static javax.swing.JOptionPane.OK\u CANCEL\u选项;
导入静态javax.swing.JOptionPane.PLAIN_消息;
导入java.awt.event.FocusAdapter;
导入java.awt.event.FocusEvent;
导入java.awt.event.HierarchyEvent;
导入java.awt.event.HierarchyListener;
导入javax.swing.JButton;
导入javax.swing.JComponent;
导入javax.swing.JLabel;
导入javax.swing.JOptionPane;
导入javax.swing.JPasswordField;
导入javax.swing.JRootPane;
导入javax.swing.JTextField;
导入javax.swing.SwingUtilities;
公共类FocusPasswordFieldNoctionPaneDemo实现Runnable
{
公共静态void main(字符串[]args)
{
调用器(新的FocusPasswordFieldInOptionPaneDemo());
}
@凌驾
公开募捐
{
JTextField uname=新的JTextField(“用户”);
JPasswordField passwd=新的JPasswordField();
JTextField serverAddress=新的JTextField(“服务器”);
JTextField端口=新的JTextField(Integer.toString(1337));
最终JComponent[]输入=新JComponent[]{new JLabel(“用户名”),uname,new JLabel(“密码”),passwd,
新JLabel(“服务器地址”)、serverAddress、新JLabel(“服务器端口”)、Port};
确保PasswordFieldGetsFocus(passwd);
int answer=JOptionPane.showConfirmDialog(空,输入,“输入连接详细信息”,确定\取消\选项,普通\消息);
System.out.println(应答);
}
/**
*{@link JOptionPane}使对话框中的[OK]按钮成为默认按钮,并使其成为焦点。
*
*因此,通过几个侦听器,我们可以等待按钮获得永久焦点,然后将焦点切换到密码字段。
*/
私有void makeSurePasswordFieldGetsFocus(最终JPPasswordField密码)
{
passwd.addHierarchyListener(新的HierarchyListener()
{
HierarchyListener HierarchyListener=this;
@凌驾
公共无效层次结构已更改(层次结构事件e)
{
JRootPane rootPane=SwingUtilities.getRootPane(passwd);
if(rootPane!=null)
{
final JButton-okButton=rootPane.getDefaultButton();
如果(确定按钮!=null)
{
addFocusListener(新的FocusAdapter()
{
@凌驾
获得公共无效焦点(焦点事件e)
{
如果(!e.isTemporary())
{
passwd.requestFocusInWindow();
passwd.removeHierarchyListener(hierarchyListener);
okButton.removeFocusListener(此);
}
}
});
}
}
}
});
}
}

这个解决方案是可行的,但有点粗糙。。。另一种方法是创建一个自定义的“DatabaseConnectionDialog”,类似于@syb0rg的答案。

密码字段已经可见,我不确定(很高兴出错),但我认为这不会像您预期的那样起作用。好吧。。。然后尝试HierarchyListener:-)AddxxListener似乎都不起作用。ComponentShowed不会因为某些原因被ComponentListener调用,hierarchyChanged with HierarchyListener只会在passwd字段可见之前被调用(多次)。我尝试过大多数其他类型的侦听器,但都没有成功。