Вызывать ряд действий при нажатии клавиши Enter

У меня есть один проект Swing, и у меня есть прослушиватель действий на JTextField для клавиши Tab следующим образом.

Внутри прослушивателя действий есть JOptionPane.showMessageDialog(). А при нажатии Tab на панели опций появится информационное сообщение.

Моя проблема в том, что когда я нажимаю Enter на кнопке OK диалогового окна информационного сообщения, вызывается ряд действий, а именно Tab действие JTextField и Enter действие btnNewButton.

Если я использую щелчок мышью на кнопке «ОК» в диалоговом окне «Сообщение об ошибке», все в порядке и без проблем.

Могу ли я решить эту проблему, используя привязки клавиш вместо прослушивателя клавиш?

Пожалуйста, предложите решение

import java.awt.EventQueue;
import java.awt.KeyboardFocusManager;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Collections;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;

public class Test extends JFrame {
    private JPanel contentPane;
    private JTextField textField;
    private JButton btnNewButton;
    private JDialog dialog;

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    Test frame = new Test();
                    frame.setVisible(true);
                }
                catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    public Test() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 450, 300);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        setLocationRelativeTo(null);
        contentPane.setLayout(null);

        textField = new JTextField();
        textField.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
                Collections.emptySet());
        textField.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                if (evt.getKeyCode() == KeyEvent.VK_TAB) {
                    JOptionPane.showMessageDialog(dialog, " Please Press ENTER Key", "information",
                            JOptionPane.INFORMATION_MESSAGE);

                    btnNewButton.grabFocus();
                }
            }
        });
        textField.setBounds(73, 28, 178, 28);
        contentPane.add(textField);
        textField.setColumns(10);

        btnNewButton = new JButton("New button");
        btnNewButton.addKeyListener(new KeyAdapter() {
            @Override
            public void keyReleased(KeyEvent e) {
                if (e.getKeyCode() == KeyEvent.VK_ENTER) {
                    JOptionPane.showMessageDialog(dialog, " That Invoked New Button Also", "Error",
                            JOptionPane.ERROR_MESSAGE);
                }
            }
        });
        btnNewButton.setBounds(223, 137, 117, 25);
        contentPane.add(btnNewButton);

        JLabel lblNewLabel = new JLabel("Please Press TAB Key");
        lblNewLabel.setBounds(83, 55, 183, 15);
        contentPane.add(lblNewLabel);

        dialog = new JDialog();
        dialog.setAlwaysOnTop(true);
    }
}

person Renoj Joseph    schedule 13.11.2020    source источник
comment
Могу ли я решить эту проблему, используя привязки клавиш вместо прослушивателя клавиш? Ну, .. да, вы могли бы, но моей первой мыслью было DocumentListener. Общие советы: 1) Используйте логичную и последовательную форму отступов строк и блоков кода. Отступы предназначены для облегчения понимания потока кода! В большинстве IDE есть сочетание клавиш специально для форматирования кода. 2) Чтобы быстрее помочь, изменить, чтобы добавить минимальный воспроизводимый пример или Короткий, автономный, правильный пример. 3) Графические интерфейсы Java должны работать с разными ОС, размером экрана, разрешением экрана и т. д..   -  person Andrew Thompson    schedule 13.11.2020
comment
.. используя разные PLAF в разных регионах. Как таковые, они не способствуют идеальной компоновке пикселей. Вместо этого используйте менеджеры макетов или их комбинации вместе с отступами и границами макета для пробел.   -  person Andrew Thompson    schedule 13.11.2020
comment
@ Андрей Я отредактировал код, и теперь он воспроизводим. Пожалуйста, предложите мне необходимые модификации.   -  person Renoj Joseph    schedule 13.11.2020


Ответы (1)


Проблема в том, что вы переопределяете метод keyReleased(). JOptionPane закрывается до вызова метода keyReleased(), и поскольку вы делаете btnNewButton сфокусированным компонентом после закрытия JOptionPane, вызывается метод keyReleased(), который отображает другой JOptionPane.

Просто переименуйте метод в keyPressed().

Кроме того, вам не нужен член dialog. Первым параметром JOptionPane#showMessageDialog должен быть JFrame.

Вот ваш код с моими исправлениями.

import java.awt.EventQueue;
import java.awt.KeyboardFocusManager;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Collections;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;

public class Test extends JFrame {
    private JPanel contentPane;
    private JTextField textField;
    private JButton btnNewButton;

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    Test frame = new Test();
                    frame.setVisible(true);
                }
                catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    public Test() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 450, 300);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        setLocationRelativeTo(null);
        contentPane.setLayout(null);

        textField = new JTextField();
        textField.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
                Collections.emptySet());
        textField.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                if (evt.getKeyCode() == KeyEvent.VK_TAB) {
                    JOptionPane.showMessageDialog(Test.this, " Please Press ENTER Key", "information",
                            JOptionPane.INFORMATION_MESSAGE);
                    btnNewButton.grabFocus();
                }
            }
        });
        textField.setBounds(73, 28, 178, 28);
        contentPane.add(textField);
        textField.setColumns(10);

        btnNewButton = new JButton("New button");
        btnNewButton.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                if (e.getKeyCode() == KeyEvent.VK_ENTER) {
                    JOptionPane.showMessageDialog(Test.this, " That Invoked New Button Also", "Error",
                            JOptionPane.ERROR_MESSAGE);
                }
            }
        });
        btnNewButton.setBounds(223, 137, 117, 25);
        contentPane.add(btnNewButton);

        JLabel lblNewLabel = new JLabel("Please Press TAB Key");
        lblNewLabel.setBounds(83, 55, 183, 15);
        contentPane.add(lblNewLabel);
    }
}

Обратите внимание, что (по крайней мере, в JDK 15) нет необходимости явно задавать операцию закрытия по умолчанию для JFrame, поскольку по умолчанию EXIT_ON_CLOSE

person Abra    schedule 13.11.2020