2011-10-05 12 views
3

我想显示一个JOptionPane,其中有一个初始焦点JTextField,并且,只要用户按下ENTER键,我希望它执行一个操作,输入文本文本域。JOptionPane的元素之间的备选焦点

我做了一些广泛的搜索,我没有找到任何可以帮助我的。我将在这里声明我管理至今:

这是我得到

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”按钮。

我试过监听器,但似乎我无法从里面访问不是最终的数据 - 即文本字段。

回答

4

基本上,你有相互打架的几个问题得到解决:-)

  • 最初主要组件:这是一个有点一招,用createOptionDialog方法传入多个自定义组件的消息字段和初始值为“initialSelectionValue”。
  • 自定义按钮:再次将自定义文本(或真正的按钮,并不重要)作为选项参数传递是一种技巧。实际上,它是为用户提供的选择,其中之一是最初选择的(然后获得焦点)
  • 对文本域的操作第一个按钮(封闭根窗格中的==默认按钮):在此领域本身矗立在使两者的方法,因为它吃回车键

最后可以通过JTextField的自定义子类来解决,就像BasicOptionPaneUI使用的使用inputdialog,它在所示结束 - 仅在解决前两个问题时才有用于optionPane上下文。我还没有看到一个完全令人满意的解决方案:将“消息”概念与“选项”概念混合,将选项窗口混淆为而不是设置根窗格的默认按钮。所以最后,你最好不要使用第一个技巧,坚持使用“选项”概念,然后通过在字段的addNotify中请求传输来欺骗焦点。

@Override 
    public void addNotify() { 
     super.addNotify(); 
     SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       requestFocus(); 
      } 
     });     
    } 

不吃某些keyStrokes的自定义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 && 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); 
+0

非常感谢您的回复! :)我会试一试,并会在这里发布。亲切的问候,菲利普。 –

+0

感谢伟大的教训+1 – mKorbel