У меня очень странный сценарий, который, к сожалению, я не могу предотвратить в моем приложении Swing. Однако, когда это происходит, это имеет серьезные последствия для меня. Возможно, кто-то может помочь!Предотвращение разрыва JTextField/JDialog с повторной передачейFocus()
Базовая настройка выглядит следующим образом:
- среды Linux.
- Несколько JTextFields в JFrame.
- JTextFields push through transferFocus() при нажатии клавиши Enter.
- JDialog появляется при выходе из одного из полей, для которого требуется нажать клавишу Enter, чтобы удалить его.
ситуация, которая вызывает вопрос заключается в следующем:
- клавишу ввода удерживается в нажатом положении в течение нескольких секунд.
Когда клавиша ввода удерживается нажатой, фокус, очевидно, пролетает через разные текстовые поля. Когда появится диалоговое окно, клавиша ввода закрывает его, в результате чего фокус будет продолжать пролетать через текстовые поля. В конце концов, через пару секунд Java разбивается. Текстовые поля немедленно перестают отвечать на нажатия клавиш - вы вообще ничего не можете вводить в них. Кроме того, все кажется нормальным - вы можете щелкнуть мышью и сосредоточиться на разных текстовых окнах, закрыть приложение и т. Д.
Я создал простой тестовый пример, который вы можете использовать для воссоздания ситуации.
фрейм:
public class TestSwing extends JFrame {
JTextField jtfText1, jtfText2, jtfText3;
TextHandler handler = null;
public TestSwing() {
super("TextField Test Demo");
Container container = getContentPane();
container.setLayout(new FlowLayout());
jtfText1 = new MyJTextField(10);
jtfText2 = new MyJTextField(10);
jtfText3 = new MyJTextField(10);
container.add(jtfText1);
container.add(jtfText2);
container.add(jtfText3);
handler = new TextHandler();
jtfText3.addActionListener(handler);
setSize(325, 100);
setVisible(true);
}
private class TextHandler implements ActionListener {
public void actionPerformed(ActionEvent e) {
JOptionPane.showConfirmDialog(null, "wait!");
}
}
public static void main(String args[]) {
TestSwing test = new TestSwing();
test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Обычай JTextField:
public class MyJTextField extends JTextField {
public MyJTextField(int len) {
super(len);
addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent evt) {
int key = evt.getKeyCode();
if (key == KeyEvent.VK_ENTER)
transferFocus();
}
});
}
}
Чтобы ответить на любые возможные вопросы Спереди:
- Ввода ключ должен использоваться для передачи фокуса.
- Распаковка клавиши Enter происходит от пользователя, оставляющего что-то на клавиатуре (это в розничной среде, так что это часто случается).
- Простое закрытие и перезапуск приложения на самом деле не является вариантом, поскольку в компьютер не подключена мышь. Приложение запускается автоматически при запуске, что делает этот сценарий разрушительным, так как единственным способом устранить проблему является перезагрузка машины.
- Машины не очень мощные (обработка & памяти), что почему-то вызывает проблему намного быстрее, чем когда она воссоздана на машине разработки.
Является ли это ошибкой на Java? Может ли кто-нибудь подумать о способе предотвратить это?
Ближайший я могу добраться до предотвращения этого не происходит, поставить сон (500) вызова в JDialog (шахта продлена) до закрытия, но это на самом деле не большой фикс ...
У меня есть испытал это в JDK 1.6, 1.7 и 1.8.Хотя в более поздних версиях требуется больше времени для того, чтобы текстовые поля перестали отвечать на запросы, это все равно произойдет в конечном итоге.
Заранее благодарен!
Xandel
Это была отличная идея! Простой, аккуратный и эффективный. Мой JDialog, к сожалению, также использует KeyListener, так как нет фактической кнопки, чтобы щелкнуть, поэтому я расширил ваше решение, чтобы иметь «системную» переменную lastTime, и применил ту же концепцию к моей реализации JDialog. – Xandel