Установка фокуса компонента в JOptionPane.showOptionDialog () - PullRequest
12 голосов
/ 06 июня 2011

Для того, чтобы в диалоговом окне ввода были пользовательские заголовки кнопок, я создал следующий код:

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();
}

Как мне переместить фокус (курсор) в текстовое поле какотображается диалоговое окно?

ОБНОВЛЕНИЕ

Это не работает для меня, я имею в виду, текстовое поле не имеет фокуса: OS: 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();
    }
  }
}

Ответы [ 8 ]

14 голосов
/ 06 июня 2011

Диалоговое окно Focus показывает, как вы можете легко установить фокус на любом компоненте в модальном диалоговом окне.

8 голосов
/ 29 января 2014
    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());
    }
5 голосов
/ 06 июня 2011

передача нуля в качестве последнего аргумента является решением. По крайней мере, у меня это сработало.

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. Последний аргумент определяет компонент по умолчанию, который также получает фокус, и передача значения 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);
                }
              }
            }
          }
        }
      }

    });
4 голосов
/ 14 июля 2011

У меня была такая же проблема с RequestFocusListener (), не работающим в Linux, после обсуждения http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5018574 я обнаружил, что добавление 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) {}
}
3 голосов
/ 02 апреля 2014

Хитрость заключается в том, чтобы (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;
} );
1 голос
/ 19 июля 2017

Лучший способ сделать это: создать 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);
1 голос
/ 06 июня 2011

Попробуйте это

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();
}
0 голосов
/ 16 мая 2018

Я нашел решение! Очень примитивно, но работает.

Просто прыгайте на поле с помощью 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());
            }
        }
    });
}

Если местоположение вашего компонента является динамическим, вы можете без ограничений выполнять цикл while, но добавьте слушателя фокуса на компонент, чтобы остановить цикл после его прибытия.

...