我正在尝试显示一个带有 JTextField
的 JOptionPane
,它具有初始焦点,一旦用户按下 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”按钮。
我试过监听器,但似乎我无法从其中访问非最终数据(即文本字段)。
最佳答案
基本上,您有几个问题正在相互解决 :-)
- 初始聚焦组件:使用 createOptionDialog 方法在消息字段中传入多个自定义组件,并将初始组件作为“initialSelectionValue”传递,这有点小技巧。
- 自定义按钮:再次将自定义文本(或真正的按钮,并不重要)作为选项参数传递是一个小技巧。实际上,它意味着用户可以选择,其中之一是最初选择的(然后获得焦点)
- 对文本字段和第一个按钮的操作(==封闭根 Pane 中的默认按钮):此处字段本身阻碍了这两个操作,因为它吃回车键
最后一个可以通过 JTextField 的自定义子类来解决,就像 BasicOptionPaneUI 用于 inputDialog 一样,它显示在最后 - 仅当前两个被解决时才在 optionPane 上下文中有用。我还没有看到一个完全令人满意的解决方案:将“消息”的概念与“选项”的概念混合会使 optionPane 混淆为 not 设置 rootpane 的默认按钮。所以最后,您最好不要使用第一个技巧,坚持使用“选项”概念,然后通过在字段的 addNotify 中请求传输来欺骗焦点。
@Override
public void addNotify() {
super.addNotify();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
requestFocus();
}
});
}
自定义的 JTextField 不吃某些 keyStrokes。它称为 MultiplexingTextField 并在配置为这样做时传递 keyStrokes 的处理:
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 && condition != JComponent.WHEN_IN_FOCUSED_WINDOW
&& 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);
关于java - JOptionPane 元素之间的交替焦点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7666309/