2014-06-20 50 views
-1

當您鍵入Tab鍵時,如何讓Java組合框接受突出顯示的值,就像您在鍵入Enter時一樣? 我認爲這是一個UI規範,並且已經在網站和桌面程序中看到過它,所以我不明白爲什麼Java默認不會這樣做。 (退出鍵在那裏取消。)如何使用Tab鍵在Swing JComboBox中接受值

我發現了幾個相關的問題,包括如何讓Enter的行爲像Tab,但它變得更難以走另一條路,所以我會發布我如何做到了。也許我錯過了一個簡單的方法!

特別是,the closest posting I could find沒有工作,因爲tab鍵已被焦點系統佔用。 其他相關問題有herehere,也許有些提示here

回答

1

這很棘手,因爲輸入密鑰處理方式無法訪問。它發生在BasicComboBoxUI.actionPerformed()的大型if-else樹中。這是從無法訪問的彈出式菜單中將值拉入組合框的地方。這也很棘手,因爲在你使用它們做任何事情之前,焦點遍歷的關鍵事件都被消耗掉了。

爲了得到這個工作,我必須從焦點遍歷鍵中移除Tab,在JComboBox上覆蓋processKeyEvent(),並且對不起!將假Enter-key事件傳遞給超類,以便讓UI執行通常用於Enter的操作。然後我不得不手動處理焦點轉換。

這是一些代碼。 (我處理Shift-Tab鍵/向後遍歷重點以同樣的方式,這可能是矯枉過正。)

protected final JComboBox combobox = new JComboBox() { 
    @Override 
    public void processKeyEvent(KeyEvent e) {   
     if (e.getID() != KeyEvent.KEY_PRESSED 
       || e.getKeyCode() != KeyEvent.VK_TAB) { 
      super.processKeyEvent(e); 
      return; 
     } 

     if (isPopupVisible()) { 
      assert e.getSource() instanceof Component; 
      KeyEvent fakeEnterKeyEvent = new KeyEvent((Component) e.getSource(), 
        e.getID(), 
        e.getWhen(), 
        0,     // No modifiers. 
        KeyEvent.VK_ENTER, // Enter key. 
        KeyEvent.CHAR_UNDEFINED); 
      super.processKeyEvent(fakeEnterKeyEvent); 
     } 
     if (e.getModifiers() == 0) { 
      transferFocus(); 
     } else if (e.getModifiers() == KeyEvent.SHIFT_MASK) { 
      transferFocusBackward(); 
     } 
    } 
}; 

// Remove tabs from focus traversal keylists. 
// Forward. 
Set<AWTKeyStroke> focuskeys = Sets.newHashSet(combobox.getFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS)); 
KeyStroke lTabKeystroke = KeyStroke.getKeyStroke("pressed TAB"); 
focuskeys.remove(lTabKeystroke); 
combobox.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, focuskeys); 
// Backward. 
focuskeys = Sets.newHashSet(combobox.getFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS)); 
KeyStroke lShiftTabKeystroke = KeyStroke.getKeyStroke("shift pressed TAB"); 
focuskeys.remove(lShiftTabKeystroke); 
combobox.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, focuskeys); 
1

搖擺使用按鍵綁定來調用不同的KeyStroke都行動。 JComboBox對ENTER鍵有一個操作。請參閱Key Bindings上所有綁定的列表。

所以我認爲這將是一個簡單的情況下將輸入操作綁定到另一個KeyStroke。

果然,當我將ENTER動作綁定到RIGHT箭頭鍵時,該功能按預期工作。

但是,當我將輸入操作綁定到TAB鍵時,它不起作用。但是,彈出菜單仍然關閉。所以現在我想知道如果TAB鍵被另一個組件處理來關閉阻止新的TAB鍵綁定工作的菜單。也許其他人對此有所瞭解?

import java.awt.*; 
import java.awt.event.*; 
import javax.swing.*; 
import javax.swing.plaf.basic.*; 

public class ComboBoxTest2 extends JFrame 
{ 
    JComboBox comboBox; 
    JTextField textField; 
    String[] tabs; 
    public ComboBoxTest2() 
    { 
     String[] tabs = { "a", "b", "c", "d", "e", "f", "g" }; 

     DefaultComboBoxModel model = new DefaultComboBoxModel(tabs); 
     comboBox = new JComboBox(model); 
     add(comboBox, BorderLayout.NORTH); 
     add(new JButton("A Component To Tab To"), BorderLayout.SOUTH); 

     // This works 

     InputMap im = comboBox.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); 
     KeyStroke existingKeyStroke = KeyStroke.getKeyStroke("ENTER"); 
     KeyStroke rightKS = KeyStroke.getKeyStroke("RIGHT"); 
     im.put(rightKS, im.get(existingKeyStroke)); 

     // This doesn't work 

     comboBox.setFocusTraversalKeysEnabled(false); 
     KeyStroke tabKS = KeyStroke.getKeyStroke("TAB"); 
     im.put(tabKS, im.get(existingKeyStroke)); 
    } 
    public static void main(String[] args) 
    { 
     JFrame frame = new ComboBoxTest2(); 
     frame.setDefaultCloseOperation(EXIT_ON_CLOSE); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 
} 
+0

嗨,感謝您的跟進!有一件事我沒有提到:當我嘗試你的soln時,我實際上在im.get(ENTER)時得到了空值。不過,我看到了不同之處:我使用WHEN_FOCUSED來獲取輸入映射,而不是WHEN_ANCESTOR_OF。我現在嘗試了WHEN_ANCESTOR並確實看到了非空綁定。就像你在這裏報道的那樣,雖然爲TAB設置相同的綁定不起作用。 (還有一點需要注意:我認爲在彈出窗口不顯示的情況下,Tab和Enter應該有不同的表現,我認爲只有選項卡應該將重點放在下一個組件上。) –