Reputation: 129
Let's say, for example, that I have a JComboBox
with the elements {"example 1", "example 2", "example 3"} (please note the spaces between example and the corresponding number).
When you try to search "example 2" by typing while the combobox is selected, it closes because the space bar toggles the popup of the component.
This could be split up into two questions:
JComboBox
. How do I make it so that pressing the space bar will actually make it add " " to the search?Anyone who can answer this question properly will most definitely recieve an upvote.
Upvotes: 1
Views: 776
Reputation: 324118
You can use:
KeyStroke space = KeyStroke.getKeyStroke("pressed SPACE");
InputMap im = comboBox.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
im.getParent().remove(space);
The problem with this solution is that it removes the popup functionality for all combo boxes in your application, which may or may not be what you want.
Edit:
If this is for a single combo box the more work required. You need to invoke the comboBox.selectWithKeyChar() method. This is easy enough to do with a custom Action. Unfortunately this still doesn't work because this code ends up invoking the DefaultKeySelectionManager which depends on some class variables contained in the BasicComboBoxUI class. Therefore I ended up writing my own ow KeySelectionManager which keeps all these variable local. This is what I came up with:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.plaf.basic.*;
import javax.swing.text.*;
public class ComboBoxKeySelection extends JPanel
{
JComboBox<String> comboBox;
public ComboBoxKeySelection()
{
String[] data =
{
" 1", " 2", " 3", " 4",
"a", "ab", "abc", "abcd",
"b1", "b2", "b3", "b4", "be",
"c", "d", "e", "f"
};
comboBox = new JComboBox<String>( data );
add( comboBox );
Action search = new AbstractAction()
{
public void actionPerformed(ActionEvent e)
{
comboBox.selectWithKeyChar( " ".charAt(0) );
}
};
KeyStroke space = KeyStroke.getKeyStroke("typed SPACE");
comboBox.getActionMap().put("spacePopup", search);
comboBox.setKeySelectionManager( new MyKeySelectionManager(comboBox) );
}
static class MyKeySelectionManager implements JComboBox.KeySelectionManager
{
private JComboBox comboBox;
private JList listBox;
private boolean useComboBoxModel;
private long timeFactor;
private long lastTime;
private long time;
private String prefix = "";
private String typedString = "";
public MyKeySelectionManager(JComboBox comboBox)
{
this.comboBox = comboBox;
Long l = (Long)UIManager.get("ComboBox.timeFactor");
timeFactor = l == null ? 1000L : l.longValue();
Object child = comboBox.getAccessibleContext().getAccessibleChild(0);
if (child instanceof BasicComboPopup)
{
BasicComboPopup popup = (BasicComboPopup)child;
listBox = popup.getList();
useComboBoxModel = false;
}
else
{
listBox = new JList();
useComboBoxModel = true;
}
}
public int selectionForKey(char aKey, ComboBoxModel aModel)
{
if (useComboBoxModel)
{
listBox.setModel( aModel );
}
time = System.currentTimeMillis();
boolean startingFromSelection = true;
int startIndex = comboBox.getSelectedIndex();
if (time - lastTime < timeFactor)
{
typedString += aKey;
if((prefix.length() == 1) && (aKey == prefix.charAt(0)))
{
// Subsequent same key presses move the keyboard focus to the next
// object that starts with the same letter.
startIndex++;
}
else
{
prefix = typedString;
}
}
else
{
startIndex++;
typedString = "" + aKey;
prefix = typedString;
}
lastTime = time;
if (startIndex < 0 || startIndex >= aModel.getSize())
{
startingFromSelection = false;
startIndex = 0;
}
int index = listBox.getNextMatch(prefix, startIndex, Position.Bias.Forward);
if (index < 0 && startingFromSelection)
{
// wrap
index = listBox.getNextMatch(prefix, 0, Position.Bias.Forward);
}
return index;
}
}
private static void createAndShowUI()
{
JFrame frame = new JFrame("ComboBoxKeySelection");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add( new ComboBoxKeySelection() );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}
Upvotes: 4
Reputation: 2855
you could catch the keypressed event and simply append the " " at the desired string.
Upvotes: 0