在JOptionPane.showOptionDialog()中设置组件焦点

为了在输入对话框中有自定义按钮标题,我创建了以下代码:

String key = null; JTextField txtKey = new JTextField(); int answerKey = JOptionPane.showOptionDialog(this, new Object[] {pleaseEnterTheKey, txtKey}, decryptionKey, JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, new Object[] {okCaption, cancelCaption}, okCaption); if (answerKey == JOptionPane.OK_OPTION && txtKey.getText() != null) { key = txtKey.getText(); } 

如何在显示对话框时将焦点 (光标)移动到文本字段?

UPDATE

这对我不起作用,我的意思是文本字段没有焦点:操作系统:Fedora – Gnome

 public class Test { public static void main(String[] args) { String key = null; JTextField txtKey = new JTextField(); txtKey.addAncestorListener(new RequestFocusListener()); int answerKey = JOptionPane.showOptionDialog(null, new Object[]{"Please enter the key:", txtKey}, "Title", JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, new Object[]{"OKKK", "CANCELLLL"}, "OKKK"); if (answerKey == JOptionPane.OK_OPTION && txtKey.getText() != null) { key = txtKey.getText(); } } } 

Dialog Focus显示如何轻松地将焦点设置在modal dialog中的任何组件上。

  public static String getPassword(String title) { JPanel panel = new JPanel(); final JPasswordField passwordField = new JPasswordField(10); panel.add(new JLabel("Password")); panel.add(passwordField); JOptionPane pane = new JOptionPane(panel, JOptionPane.QUESTION_MESSAGE, JOptionPane.OK_CANCEL_OPTION) { @Override public void selectInitialValue() { passwordField.requestFocusInWindow(); } }; pane.createDialog(null, title).setVisible(true); return passwordField.getPassword().length == 0 ? null : new String(passwordField.getPassword()); } 

传递null作为最后一个参数是解决方案。 至少它对我有用。

 String key = null; JTextField txtKey = new JTextField(); int answerKey = JOptionPane.showOptionDialog(this, new Object[] {pleaseEnterTheKey, txtKey}, decryptionKey, JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, new Object[] {okCaption, cancelCaption}, null); if (answerKey == JOptionPane.OK_OPTION && txtKey.getText() != null) { key = txtKey.getText(); } 

但即便是这个解决方案也带来了另

聚焦组件和默认组件是不同的。 默认组件或默认按钮是按下ENTER KEY触发其onclick的按钮。最后一个参数定义了获取焦点的默认组件,并且传递null会带来没有默认组件的问题! 我通过这种方式为我的代码解决了它,但我想这不是最佳实践:

 String key = null; final JTextField txtKey = new JTextField(); txtKey.addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { int keyCode = e.getKeyCode(); if (keyCode == 10) { //enter key Container parent = txtKey.getParent(); while (!(parent instanceof JOptionPane)) { parent = parent.getParent(); } JOptionPane pane = (JOptionPane) parent; final JPanel pnlBottom = (JPanel) pane.getComponent(pane.getComponentCount() - 1); for (int i = 0; i < pnlBottom.getComponents().length; i++) { Component component = pnlBottom.getComponents()[i]; if (component instanceof JButton) { final JButton okButton = ((JButton)component); if (okButton.getText().equalsIgnoreCase(okCaption)) { ActionListener[] actionListeners = okButton.getActionListeners(); if (actionListeners.length > 0) { actionListeners[0].actionPerformed(null); } } } } } } }); 

在http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5018574上的讨论之后,我遇到了同样的问题,RequestFocusListener()无法在Linux上运行。我发现添加一个invokeLater现在修复了它。 ..

 public class RequestFocusListener implements AncestorListener { public void ancestorAdded(final AncestorEvent e) { final AncestorListener al= this; SwingUtilities.invokeLater(new Runnable(){ @Override public void run() { JComponent component = (JComponent)e.getComponent(); component.requestFocusInWindow(); component.removeAncestorListener( al ); } }); } public void ancestorMoved(AncestorEvent e) {} public void ancestorRemoved(AncestorEvent e) {} } 

诀窍是(a)在文本组件上使用AncestorListener来请求焦点,当焦点再次丢失时(给予默认按钮),请在文本组件上使用FocusListener再次请求焦点(但不要在那之后继续要求关注):

 final JPasswordField accessPassword = new JPasswordField(); accessPassword.addAncestorListener( new AncestorListener() { @Override public void ancestorRemoved( final AncestorEvent event ) { } @Override public void ancestorMoved( final AncestorEvent event ) { } @Override public void ancestorAdded( final AncestorEvent event ) { // Ask for focus (we'll lose it again) accessPassword.requestFocusInWindow(); } } ); accessPassword.addFocusListener( new FocusListener() { @Override public void focusGained( final FocusEvent e ) { } @Override public void focusLost( final FocusEvent e ) { if( isFirstTime ) { // When we lose focus, ask for it back but only once accessPassword.requestFocusInWindow(); isFirstTime = false; } } private boolean isFirstTime = true; } ); 

尝试这个

 String key = null; JTextField txtKey = new JTextField(); Object[] foo = {pleaseEnterTheKey, txtKey}; int answerKey = JOptionPane.showOptionDialog(this, foo, decryptionKey, JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, new Object[] {okCaption, cancelCaption}, foo[1]); if (answerKey == JOptionPane.OK_OPTION && txtKey.getText() != null) { key = txtKey.getText(); } 

更好的方法:使用构造函数创建JOptionPane,重写selectInitialValue以设置焦点,然后使用createDialog构建对话框。

 // Replace by the constructor you want JOptionPane pane = new JOptionPane(panel, JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION) { @Override public void selectInitialValue() { textArea.requestFocusInWindow(); } }; JDialog dialog = pane.createDialog(owner, title); dialog.setVisible(true); 

我找到了解决方案! 非常原始,但有效。

只需通过java.awt跳转到该字段。 机器人使用键“Tab”。 例如:

 Robot robot = new Robot(); robot.keyPress(KeyEvent.VK_TAB); robot.delay(100); robot.keyRelease(KeyEvent.VK_TAB); 

如果你应该在“Tab”上按多次以获得你的组件,你可以使用以下方法:

 GUIUtils.pressTab(3); 

定义:

 public static void pressTab(int amountOfClickes) { SwingUtilities.invokeLater(new Runnable() { public void run() { try { Robot robot = new Robot(); int i = amountOfClickes; while (i-- > 0) { robot.keyPress(KeyEvent.VK_TAB); robot.delay(100); robot.keyRelease(KeyEvent.VK_TAB); } } catch (AWTException e) { System.out.println("Failed to use Robot, got exception: " + e.getMessage()); } } }); } 

如果您的Component位置是动态的,您可以无限制地运行while循环,但是在组件上添加一些焦点侦听器,一旦到达它就停止循环。