#java #swing #jtextfield #joptionpane
#java #качать #jtextfield #joptionpane
Вопрос:
Я пытаюсь показать a JOptionPane
с a JTextField
, который имеет начальный фокус, и, как только пользователь нажимает ENTER, я хочу, чтобы он выполнил действие с текстом, введенным в текстовое поле.
Я провел обширный поиск, и мне не удалось найти ничего, что могло бы мне помочь в этом. Я изложу здесь то, что мне удалось до сих пор:
Это то, что я получил
Object[] options = {"Option1",
"Option2"};
Object[] message = new Object[2];
message[0] = "Type in the number of the incident:";
JTextField incidentNumberTextField = new JTextField();
message[1] = incidentNumberTextField;
int n = JOptionPane.showOptionDialog(frame,
message,
"Open incident",
JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE,
null,
options,
message[1]);
if (n == -1) {
return;
}
Пока все работает нормально. Когда появляется диалоговое окно, фокус находится на текстовом поле. Однако, когда я набираю текст и нажимаю Enter, хотелось бы, чтобы он автоматически запускал кнопку «Option1».
Я пробовал прослушиватели, но, похоже, я не могу получить доступ к данным, которые не являются окончательными, то есть к текстовому полю, изнутри него.
Ответ №1:
В принципе, у вас есть несколько проблем, которые борются друг с другом, чтобы быть решенными 🙂
- изначально сфокусированный компонент: это небольшая хитрость, чтобы использовать метод createOptionDialog для передачи нескольких пользовательских компонентов в поле сообщения и начальный как «initialSelectionValue».
- пользовательские кнопки: опять же, это небольшая хитрость, чтобы передать пользовательский текст (или реальные кнопки, на самом деле не имеет значения) в качестве параметра options . На самом деле, это должен быть выбор, доступный пользователю, один из которых является первоначально выбранным (который затем получает фокус)
- действие над текстовым полем и первой кнопкой (== кнопка по умолчанию во вложенной корневой панели): здесь само поле препятствует разрешению обоих, поскольку оно потребляет клавишу ввода
последний может быть решен с помощью пользовательского подкласса JTextField, точно так же, как BasicOptionPaneUI использует для InputDialog, он показан в конце — полезен в контексте OptionPane, только если решены первые два. Для чего я не видел полностью удовлетворительного решения: смешивание понятия «сообщение» с понятием «параметры» приводит к тому, что панель опций не устанавливает кнопку rootpane по умолчанию. Итак, в конце вам, возможно, лучше не использовать этот первый трюк, придерживаться понятия «параметры», а затем изменять фокус, запрашивая передачу в поле addNotify.
@Override
public void addNotify() {
super.addNotify();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
requestFocus();
}
});
}
Пользовательское JTextField, которое не использует определенные нажатия клавиш. Это называется MultiplexingTextField и передает обработку нажатий клавиш, если для этого настроено:
public static class MultiplexingTextField extends JTextField {
private List<KeyStroke> strokes;
public MultiplexingTextField(int cols) {
super(cols);
}
/**
* Sets the KeyStrokes that will be additionally processed for
* ancestor bindings.
*/
public void addKeyStrokes(KeyStroke... keyStrokes) {
for (KeyStroke keyStroke : keyStrokes) {
getMultiplexingStrokes().add(keyStroke);
}
}
private List<KeyStroke> getMultiplexingStrokes() {
if (strokes == null) {
strokes = new ArrayList<KeyStroke>();
}
return strokes;
}
@Override
protected boolean processKeyBinding(KeyStroke ks, KeyEvent e,
int condition, boolean pressed) {
boolean processed = super.processKeyBinding(ks, e, condition,
pressed);
if (processed amp;amp; condition != JComponent.WHEN_IN_FOCUSED_WINDOW
amp;amp; getMultiplexingStrokes().contains(ks)) {
// Returning false will allow further processing
// of the bindings, eg our parent Containers will get a
// crack at them.
return false;
}
return processed;
}
}
использование в контролируемой среде:
Action fieldAction = new AbstractAction("fieldAction") {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("hello " ((JTextComponent) e.getSource()).getText());
}
};
JTextField field = new JTextField("this is a normal field");
MultiplexingTextField multiplexing = new MultiplexingTextField(20);
multiplexing.addKeyStrokes(KeyStroke.getKeyStroke("ENTER"));
field.setAction(fieldAction);
multiplexing.setAction(fieldAction);
Action action = new AbstractAction("default button action") {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("hello - got default button");
}
};
JButton button = new JButton(action);
JPanel panel = new JPanel();
panel.add(field);
panel.add(multiplexing);
panel.add(button);
// this is swingx testing support, simply replace with normal frame creation
JXFrame frame = wrapInFrame(panel, "multiplex");
frame.getRootPane().setDefaultButton(button);
Комментарии:
1. большое спасибо за ваш ответ! 🙂 Я попробую и опубликую здесь. С уважением, Фелипе.