2011-10-05 48 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