How i handle keypress event for Jcombobox in java - java

I want to add item to JCombobox , that item is what I typed in JCombobox which is item to be add. this jCombox box is editable.
How can i do this.
Ok i tryied add KeyPress event for this JCombo box but it doesn't respose
private void jbcBOXKeyTyped(java.awt.event.KeyEvent evt) {
if (evt.getKeyCode() == 13) {
System.out.println("Keypress");
jbcBOX.addItem(jbcBOX.getSelectedItem().toString());
}
}

Made a short example hope it helps.
Basically just adds ActionListener to JComboBox the ActionListener is called whenever an item is selected or added. In the ActionListener we simply check if there is an item that matches the currently selected item, if not then add the item to JComboBox if a match is found then do nothing:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class EditableJComboBox {
public EditableJComboBox() {
initComponents();
}
private void initComponents() {
JFrame frame = new JFrame("Editable JComboBox");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
String labels[] = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J"};
final JComboBox comboBox = new JComboBox(labels);
comboBox.setEditable(true);
comboBox.addActionListener(new ActionListener() {
private boolean found = false;
#Override
public void actionPerformed(ActionEvent actionEvent) {
String s = (String) comboBox.getSelectedItem();
for (int i = 0; i < comboBox.getItemCount(); i++) {
if (comboBox.getItemAt(i).toString().equals(s)) {
found = true;
break;
}
}
if (!found) {
System.out.println("Added: " + s);
comboBox.addItem(s);
}
found = false;
}
});
frame.add(comboBox);
frame.pack();
frame.setVisible(true);
}
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new EditableJComboBox();
}
});
}
}

This is explained in the Combobox tutorial. No need for dirty KeyListeners and checks for the enter key.
You make the combobox editable
You add an ActionListener which will be triggered when the enter key is hit
In your ActionListener you can update the model
Or to quote that tutorial more literally
JComboBox patternList = new JComboBox(patternExamples);
patternList.setEditable(true);
patternList.addActionListener(this);
An editable combo box fires an action event when the user chooses an item from the menu and when the user types Enter. Note that the menu remains unchanged when the user enters a value into the combo box. If you want, you can easily write an action listener that adds a new item to the combo box's menu each time the user types in a unique value.

It's worse than even this says - it seems (from using Netbeans) keyTyped etc events simply don't fire. I imagine a great number of people are here wondering why they can catch java.awt.event.KeyEvent.getKeyChar() on a JTextField but using exactly the coresponding part of the GUI Builder (in Netbeans) for a JComboBox gets them absolutely nothing!
Handling Events on a Combo Box
...
Although JComboBox inherits methods to register listeners for
low-level events — focus, key, and mouse events, for example — we
recommend that you don't listen for low-level events on a combo box.
Here's why: A combo box is a compound component — it is comprised of
two or more other components. The combo box itself fires high-level
events such as action events. Its subcomponents fire low-level events
such as mouse, key, and focus events. The low-level events and the
subcomponent that fires them are look-and-feel-dependent. To avoid
writing look-and-feel-dependent code, you should listen only for
high-level events on a compound component such as a combo box. For
information about events, including a discussion about high- and
low-level events, refer to Writing Event Listeners.

Related

How to get JComboBox to respond to enter key

I have been wracking my brain over this for a while now. When I run the following code, any other key works correctly, on invoking the showPopup() method of the JComboBox, but whenever one presses enter, nothing happens. I have tried to fire mouse events to simulate the user physically clicking on the JComboBox, but nothing has so far worked. (I could use a java.awt.Robot, but I would really prefer not to.). Here is an example program, which simply shows a JComboBox, and adds a KeyAdapter to it:
import java.awt.Dimension;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.SpringLayout;
public class Test {
public static void main(String[] args) {
JFrame testFrame = new JFrame();
testFrame.setLocationRelativeTo(null);
testFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
SpringLayout layout = new SpringLayout();
testFrame.getContentPane().setLayout(layout);
JComboBox testingComboBox = new JComboBox(new String[] {"Option 1", "Option 2", "Option 3"});
testingComboBox.addKeyListener(new KeyAdapter(){
#Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_ENTER){
testingComboBox.showPopup();
} else if (e.getKeyCode() == KeyEvent.VK_2){
testingComboBox.showPopup();
}
}
});
testFrame.add(testingComboBox);
layout.putConstraint(SpringLayout.NORTH, testingComboBox, 0, SpringLayout.NORTH, testFrame);
layout.putConstraint(SpringLayout.WEST, testingComboBox, 0, SpringLayout.WEST, testFrame);
testFrame.pack();
testingComboBox.requestFocusInWindow();
int differenceInWidth = testFrame.getWidth() - testFrame.getContentPane().getWidth();
int differenceInHeight = testFrame.getHeight() - testFrame.getContentPane().getHeight();
testFrame.setMinimumSize(new Dimension(testingComboBox.getWidth() + differenceInWidth, testingComboBox.getHeight() + differenceInHeight));
testFrame.setVisible(true);
}
}
I'm not quite sure what's going on, and would appreciate any possible help.
Note: I have also tried using an ActionListener, and that would also provide the same problem. If I put a System.out.println("Test");right before the showPopup() call, "Test" is still printed in the command line, but nothing appears.
Swing was designed to be used with Key Bindings.
The Enter key is already defined as a binding for the JComboBox, so that action is basically causing the popup to be closed. This can be demonstrated by using:
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
testingComboBox.showPopup();
}
});
By using the invokeLater() the code is placed at the end of the EDT so it executes after the default Enter key processing.
So in reality you should not be trying to listen for Enter key events since they are already handled by the UI.
Check out Key Binding Defaults for a list of the default key bindings for each component.
When you look at the list you will notice that a combo box already has an Action to toggle the popup, so if you do create a Key Binding you should use the existing Action. The above link shows you how to do this:
KeyStroke ks = KeyStroke.getKeyStroke("2");
InputMap im = comboBox.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
im.put(ks, "togglePopup");
Don't use KeyListener. Use Key Bindings instead. This should work:
testingComboBox.getInputMap().put(KeyStroke.getKeyStroke("ENTER"),
"showPopup");
testingComboBox.getActionMap().put("showPopup",
new AbstractAction() {
public void actionPerformed(ActionEvent e) {
testingComboBox.showPopup();
}
});

Java ComboBox how to populate on click add item not working

it's really simple. I want to populate a jcomboBox but only after the user press the arrow on the combobox.
I think the code is right cause i test it in a separate button and it populate the Combobox but when i create an action listener for the combobox itself it doesn't populate, Here are the code.
comboBox.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
comboBox.addItem("Item");
comboBox.addItem("Second Item");
}
It's a country city neighborhood situation . What i want is the second to be populated when the first is selected .
The first box is easy to populate (The country box) But the second box (City) I added a switch for it but it just won't populate , What i want to know is there an action i should put my code into for it to populate ?
I want to populate a jcomboBox but only after the user press the arrow on the combobox.
Why would the user look at an empty combo box and then click on the arrow? If the contents of the combo box are based on some other user Action, then that Action should cause the combo box to be populated.
Anyway, maybe you are trying to popuplate the combo box when the dropdown is displayed?
That is the user could click anywhere on the combo box, not just the down arrow.
In this case you can use a PopupMenuListener
comboBox.addPopupMenuListener(new PopupMenuListener()
{
public void popupMenuWillBecomeVisible(PopupMenuEvent e)
{
JComboBox comboBox = (JComboBox)e.getSource();
comboBox.addItem("Item1");
comboBox.addItem("Item2");
comboBox.addItem("Item3");
comboBox.addItem("Item4");
}
public void popupMenuCanceled(PopupMenuEvent e) {}
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {}
});
Edit:
It's a country city neighborhood situation .
Which is a requirement that should have been included with your original question. As people has suggested your approach is wrong. The child combo boxes should be updated when the parent is changed, not when you click the child.
See How to Update Multiple Combo Boxes for a better solution. The example there only shows 2 combo boxes, but the concept is the same for the second and third.
Pressing a JComboBox arrow doesn't trigger the ActionListener. Only making a selection does, and so your combo box will need to be populated before the arrow has been pressed. You'll have to re-think your design such as populating the combo box before the user interacts with it.
If you absolutely needed to add an action listener to the arrow button, it can be done, such as via a recursive method:
import java.awt.Component;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.*;
public class Foo extends JPanel {
private JComboBox<String> combo = new JComboBox<>();
public Foo() {
add(combo);
combo.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
// this doesn't work!!!
System.out.println("mouse pressed");
super.mousePressed(e);
}
});
recursiveAddAxnListener(combo);
}
private void recursiveAddAxnListener(Component comp) {
if (comp instanceof AbstractButton) {
((AbstractButton) comp).addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
System.out.println("added to combo's button");
}
});
} else if (comp instanceof Container) {
Component[] comps = ((Container) comp).getComponents();
for (Component component : comps) {
recursiveAddAxnListener(component);
}
}
}
private static void createAndShowGUI() {
Foo paintEg = new Foo();
JFrame frame = new JFrame("Foo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(paintEg);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
But do I recommend it? No, not at all.
Edit
You have edited your question and have added:
It's a country city neighborhood situation . What i want is the second to be populated when the first is selected .
The first box is easy to populate (The country box) But the second box (City) I added a switch for it but it just won't populate , What i want to know is there an action i should put my code into for it to populate ?
You may be asking an XY-Problem type question where you ask how do I solve X code problem when the best solution is to use an entirely different approach. In this situation I strongly recommend that you not populate the second combobox on mouse press, but rather populate it only once and do it when the first combobox selection has been made. In other words, populate the 2nd combo box in the first combo box's ActionListener. This will simplify things greatly and prevent re-population of the 2nd combobox unnecessarily.
Thank you all for your help , you have been just awesome.
I found the problem I had to have the combobox.removeallItems(); before the switch not in the switch.
This is the testing version of it.and it worked.
JComboBox comboBox = new JComboBox();
comboBox.addItem("");
comboBox.addItem("first");
comboBox.addItem("second");
comboBox.addItem("third");
comboBox.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
comboBox_1.removeAllItems();
String test = comboBox.getSelectedItem().toString();
switch (test) {
case "first":
comboBox_1.addItem("Tesing");
break;
case "second":
comboBox_1.addItem("Tesing2");
break;
case "third":
comboBox_1.addItem("Tesing three");
break;
default:
break;
}
}
});
Again , i appreciate all the help , Thank you so much.

Java Swing: Controlling focus with textfield and autocompletion dialog/menu

I have a JTextField that I'm trying to add an autocompletion menu to. But I'm having issues with how I should handle the focus.
Here's a SSCCE
package test;
import java.awt.Point;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
public class SSCCE extends JFrame implements DocumentListener {
private AutocompletionDialog dialog;
public SSCCE() {
dialog = new AutocompletionDialog ();
JTextField textField = new JTextField(20);
textField.getDocument().addDocumentListener(this);
add(textField);
setDefaultCloseOperation(EXIT_ON_CLOSE);
pack();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new SSCCE().setVisible(true);
}
});
}
public void insertUpdate(DocumentEvent e) {
Point p = this.getLocationOnScreen();
dialog.setLocation(p.x, p.y + 50);
dialog.setVisible(true);
}
public void removeUpdate(DocumentEvent e) { }
public void changedUpdate(DocumentEvent e) { }
private class AutocompletionDialog extends JDialog {
JList<String> list = new JList<>(
new String[] { "One", "Two", "Three" });
AutocompletionDialog() {
setSize(100, 100);
add(list);
}
}
}
Of course there's more logic to it in the real program, but the issue I'm having is that I want to show the autocompletion dialog/menu, but still be able to continue typing in the text field. At the same time, I also want to be able to navigate the menu with the up/down arrows and the enter key, as well as with the mouse, to select one of the completion options.
Can someone please help me with how I should proceed here? Thanks!
EDIT:
Thanks to #camickr's reply I played around a bit with setFocusableWindowState together with an InputMap/ActionMap to always keep the focus in the text field, and manually control the selected list item. The problem is that you get a visual difference when doing it that way compared to if the list had proper focus. See the screen shots.
This is what it looks like if I don't mess with the focus (this is what I want).
This is what it looks like if I run setFocusableWindowState(false)
The main differences are the highlight border (darker blue) around the selected list item, but also the blue highlight around the entire dialog. Then there's also the differences in the title bar.
(Don't mind the render artifacts, I'm connecting to a three year old virtual Linux installation using an old NX client)
EDIT 2:
I was afraid that it was the Look and Feel or OS that determined how the selected list item should look (with the highlighted border for example). But it turns out that it is indeed just the cell renderer that makes that call. Knowing that I felt much better about writing my own cell renderer, and I now have a solution that I'm happy with.
This is the code I ended up using:
private class CellRenderer extends DefaultListCellRenderer
{
#Override
public Component getListCellRendererComponent(
JList<?> jlist, Object value, int index,
boolean isSelected, boolean cellHasFocus) {
super.getListCellRendererComponent(
jlist, value, index, isSelected, cellHasFocus);
if (isSelected) {
Border border = UIManager.getBorder(
"List.focusSelectedCellHighlightBorder");
if (border == null) {
border = UIManager.getBorder(
"List.focusCellHighlightBorder");
}
setBorder(border);
}
return this;
}
}
As I show the auto completion menu the focus is given to that dialog.
To prevent focus from going to the popup window you can use:
JDialog dialog = new JDialog(...);
dialog.setFocusableWindowState( false );
...
dialog.setVisible( true );
I also want to be able to navigate the menu with the up/down arrows and the enter key
Then you need to override the default Actions provided by the text field. Check out Key Bindings for more information.
You can also check out: button highlighting using keyboard keys where I just provided a simple example of implementing an Action.

Handle RadioButton events after button clicked

help,
my questions are:
why isn't itemStateChanges triggered, I tried to put it in the inner class ButtonHandler and also in RadioButtonHandler Im having trouble with it, what is the right way to do it?
I want to trigger and check the marked JRadioButtons after the user click the "check" button.
What is the right way to check which button was clicked, I feel like comparing the strings is bad programming practise. Maybe using an ID ?
How should I make a "reset" button(start over), I want to uncheck all radio buttons and run the constructor once again.
Thank you for your help !
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import javax.swing.*;
public class ExamFrame extends JFrame {
static ArrayList<Question> qArrList;
JRadioButton a1,a2,a3,a4;
public ExamFrame() {
super("Quiz");
setLayout(new GridLayout(0, 1));
GridBagConstraints gbc = new GridBagConstraints();
Exam exam = new Exam();
qArrList = exam.getExam();
int count=0;
for(Question q : qArrList){
count++;
JLabel questionLabel = new JLabel(count+". "+q.getQustion()); //swing constant ?
ArrayList<String> ansRand = q.getAllRandomAns();
a1 = new JRadioButton(ansRand.get(0));
a2 = new JRadioButton(ansRand.get(1));
a3 = new JRadioButton(ansRand.get(2));
a4 = new JRadioButton(ansRand.get(3));
add(questionLabel);
add(a1);add(a2,gbc);add(a3);add(a4);
ButtonGroup radioGroup = new ButtonGroup(); //logical relationship
radioGroup.add(a1);radioGroup.add(a2);radioGroup.add(a3);radioGroup.add(a4);
}
//buttons:
JButton checkMe = new JButton("Check Exam");
JButton refresh = new JButton("Start Over");
ButtonHandler handler = new ButtonHandler();
checkMe.addActionListener(handler);
refresh.addActionListener(handler);
add(checkMe);
add(refresh);
}
/** Listens to the radio buttons. */
public class ButtonHandler implements ActionListener
{
public void actionPerformed (ActionEvent e) {
if(e.getActionCommand().equals("Start Over")){ //id?
//how to do this?
}
else{
RadioButtonHandler handler = new RadioButtonHandler();
a1.addItemListener(handler);
System.out.println("success?");
}
JOptionPane.showMessageDialog(ExamFrame.this, String.format("You pressed: %s", e.getActionCommand()));
}
public void itemStateChanged(ItemEvent e) //can i add it here?
{
JOptionPane.showMessageDialog(ExamFrame.this, String.format("yes?"));
System.out.println("success!");
}
}
public class RadioButtonHandler implements ItemListener
{
public void itemStateChanged(ItemEvent e)
{
JOptionPane.showMessageDialog(ExamFrame.this, String.format("radio state changed"));
}
}
}
why "itemStateChanges" isn't triggered, i tried to put it in the inner
class "ButtonHandler" and also in "RadioButtonHandler" Im having
troubles with it, what is the right way to do it? I want to trigger
and check the marked JRadioButtons after the user click the "check"
button.
ButtonHandler is implemented with ActionListener only:
public class ButtonHandler implements ActionListener{}
The itemStateChanged(ItemEvent) function belongs to ItemListener. This function is triggered if state of a source component to which this listener is registered gets changed. So implement the ItemListener. However, one more thing to note, that JButton doesn't respond to ItemListener but JRadioButton will. Because this Item events are fired by components that implement the ItemSelectable interface. Some example of such components are: check boxes, check menu items, toggle buttons and combo boxes including Radio Buttons as mentioned above.
What is the right way to check which button was clicked, i feel like
comparing the strings is wrong programming. Maybe using an ID
Well using the event source function: e.getSource(), check whither the type of the source is your expected type and cast it to appropriate type. And then you can use getName(String) function and check the name you were expecting. Of-course you should assign the name using setName(String) after initialization of component. Or using the component reference directly if it is declared in the Class context and you have direct access to the component.
#Override
public void itemStateChanged(ItemEvent e) {
if(e.getSource() instanceof JCheckBox)
{
JCheckBox checkBox = (JCheckBox)e.getSource();
if(checkBox.getName().equals("expectedName"))
; // do my thing
}
}
How should i make a "reset" button(start over), i want to uncheck all
radio buttons and run the constructor once again.
Well you are working with ButtonGroup. And ButtonGroup has a nice function: clearSelection() to help with whatever(I could not understand the part: run the constructor part) you want.
Edit: As you wanted me to see an ItemListener implemented class, Yes i can see that But:
i can not see that you have actually registered an instance of that class(a1.addItemListener(handler);) to any component before performing any action on the component to which ButtonHandler is registered to: checkMe, refresh
In addition to that, in this action performed function, you are checking with
action command, which you haven't even set with JButton.setActionCommand(String) function. You should not assign a (Item)listener depending on event-occurrence of another (Action)listener.
Tutorial:
How to Write an ItemListener
How to Write an ActionListener
How to Use the ButtonGroup Component

How to link a hotkey to a button in java?

I have four radio buttons and they're all part of a radioGroup. How can I link hotkeys to each of the buttons? What I want to do is link the keys '1', '2', '3' and '4' to each corresponding radiobutton.
buttonGroup1 = new javax.swing.ButtonGroup();
quizBut1 = new javax.swing.JRadioButton();
quizBut2 = new javax.swing.JRadioButton();
quizBut4 = new javax.swing.JRadioButton();
quizBut3 = new javax.swing.JRadioButton();
Use a KeyListener - you can attach them to just about any component in Swing.
What you'll probably do is attach a KeyListener to the primary JFrame in your application to capture all keypresses, and depending on which key was pressed, you will then trigger changes in the UI accordingly (e.g the selecting of a given radio button).
It's important that you attach the KeyListener to a container that will have keybaord focus pretty much all the time. You cannot, in this case, attach the KeyListener to the radio buttons themselves because the KeyListeners only see events for which they have focus. When a KeyEvent isn't absorbed by a given object, the KeyEvent is then passed on to its parent component to see if it wants to do anything with the event, and on and on all the way up to the application's window. If no KeyListener does anything with the event and you've gone all the way to the root of the component hierarchy, then nothing happens in response to the keypress and the event is essentially discarded.
as well, you could use ActionMap and KeyStroke. Some rough snippet, modify it:
class KeyAction extends AbstractAction {
JRadioButton b;
KeyAction(JRadioButton b) {
super();
this.b = b;
}
#Override
public void actionPerformed(ActionEvent e) {
b.setSelected(true);
}
}
b1.setAction(new KeyAction(b1));
b2.setAction(new KeyAction(b2));
b3.setAction(new KeyAction(b3));
bindHotkey('1', "1", b1.getAction());
bindHotkey('2', "2", b2.getAction());
bindHotkey('3', "3", b3.getAction());
..............
void bindHotkey(char keyChar, String name, Action action) {
KeyStroke ks = KeyStroke.getKeyStroke(keyChar);
container.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(ks, name);
container.getActionMap().put(name, action);
}
You can use this also http://pastebin.com/UvkjD0g5

Categories

Resources