I have two JPanels inside another JPanel. One of them has a JTextField inside, another few JButtons. I want focus to be set on the JTextField every time user starts typing (even when one of the buttons has focus at the moment).
KeyListener won't work, because in order for it to trigger key events, the component it is registered to must be focusable AND have focus, this means you'd have to attach a KeyListener to EVERY component that might be visible on the screen, this is obviously not a practical idea.
Instead, you could use a AWTEventListener which allows you to register a listener that will notify you of all the events been processed through the event queue.
The registration process allows you to specify the events your are interested, so you don't need to constantly try and filter out events which your not interested in
For example. Now, you can automatically focus the textField when a key is triggered, but you should check to see if the event was triggered by the text field and ignore it if it was
One of the other things you would be need to do is re-dispatch the key event to the text field when it isn't focused, otherwise the field will not show the character which triggered it...
Something like...
if (Character.isLetterOrDigit(e.getKeyChar())) {
filterField.setText(null);
filterField.requestFocusInWindow();
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
filterField.dispatchEvent(e);
}
});
}
as an example
You need to attach a KeyListener to all controls in your JPanel, with a reference to the JTextField you want to focus like so:
panel.addKeyListener(new KeyPressedListener(yourTextField));
button1.addKeyListener(new KeyPressedListener(yourTextField));
button2.addKeyListener(new KeyPressedListener(yourTextField));
class KeyPressedListener implements KeyListener
{
private JTextField textFieldToFocus;
public KeyPressedListener(JTextField textFieldToFocus)
{
this.textFieldToFocus = textFieldToFocus;
}
#Override
public void keyPressed(KeyEvent e) {
textFieldToFocus.requestFocus();
}
}
Related
I've found many solutions on web about, but none is suitable for my problem. I have in a JFrame a KeyBoard that, on click, writes in a JTextField which is in another JFrame.
The keyboard appears thanks to an OnClickEvent in a JText, something like iphone keyboard.
How can I link the buttons to the JTextField in the other frame?
First your Swing keyboard needs to know where to pass the values. Add a JTextComponent field variable and a setter for it:
private JTextComponent textComponent;
JTextComponent is the base class for JTextField, JTextArea, etc ...
Then you need to write an ActionListener that handles the actions:
private class KeyboardActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
try {
JButton key = (JButton) e.getSource();
textComponent.getDocument().insertString(textComponent.getCaretPosition(), key.getText(), null);
} catch (BadLocationException ex) {
Logger.getLogger(KeyboardDialog.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Third step is to add all your buttons to that action listener. When a button is clicked, it will get the button from the ActionEvent, and insert its value at the current carret position. Keep in mind that this will not handle function keys. For that, have a look at JTextComponent.
I am using a JDialog to get payment info, paymentAmount and Date is submitted by a JTextfield and a datechooser.beans.DateChooserCombo.
When the user close the JDialog or clicks Cancel, JDialog closes.But when they click the Payment button and JDialog reappears, previously submitted inputs are shown.
I want JDialog to be default state whenever it appears.Is there a default way to do this, or i have to create my own reset method?
When you close a dialog it is not destroyed. It will just become invisible, but it still contains everything as it was when it was closed.
You may override the function setVisible() and reinitialize it if the dialog should be shown again.
#Override
public void setVisible(boolean bVisible)
{
if(bVisible == false)
{
super.setVisible(bVisible);
return;
}
initMyValues();
super.setVisible(bVisible);
return;
}
Alternatively you could create a WindowListener and then you get notified about various state changes of the window. Depends on what suits your needs better. The WindowListener doesn't require you to create a separate class, jsut to override the setVisible(), but you have to add some extra function required by the interface.
Another workaround would be to set a windowListener to your dialog.
myDialog.addWindowListener(new WindowListener() {
/*Implements over methods here*/
#Override
public void windowClosing(WindowEvent e) {
//set default values here
}});
I have a JFrame with multiple panels that accumulates in a fairly complex Swing UI. I want to add Keyboard support so that regardless of component focus a certain Key press, for example the [ENTER] key, causes a listener to react.
I tried adding a KeyListener to the JFrame but that doesn't work if another JComponent is selected which changes focus.
Is there a proper way to do this?
Registering a KeyEventDispatcher with the KeyboardFocusManager allows you to see all key events before they are sent to the focused component. You can even modify the event or prevent it from beeing delivered to the focused component:
KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(
new KeyEventDispatcher() {
public boolean dispatchKeyEvent(KeyEvent e) {
//Get the char which was pressed from the KeyEvent:
e.getKeyChar();
//Return 'true' if you want to discard the event.
return false;
}
});
If you just want to get the key inputs for one window / component or just for specific keys, you can use KeyBindings as kleopatra suggested. As an example on how to register to the keyboard event on Enter pressed (You may use any VK_ provided by KeyEvent, for modifiers [alt, ctrl, etc.] see InputEvent) see:
JFrame frame = new JFrame(); //e.g.
JPanel content = (JPanel)frame.getContentPane();
content.getInputMap().put(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_ENTER,0),"enterDown");
content.getActionMap().put("enterDown",new AbstractAction() {
private static final long serialVersionUID = 1l;
#Override public void actionPerformed(ActionEvent e) {
//This action is called, as the Enter-key was pressed.
}
});
The way I do it is to make the JFrame focusable and append the listener to it. Then, iterate through all the JFrame children and make everything else not focusable.
Of course this only works if you don't have text boxes or similar as they will become non editable.
I'm trying to use an editable JComboBox such that upon a user typing into the editor, possible results are displayed in the list part of the combo box.
Unfortunately, I've found that upon using either addItem(item) or getModel().addItem(item), the input typed by the user is overwritten by the first value I added. I've considered storing the editor value, adding items, and then using setSelectedItem() to fix this, but I wan't to preserve the state of any selected text/ caret position, and believe this should be something more trivial, but can't for the life of me figure it out.
JComboBox box = new JComboBox();
box.setModel(new MutableComboBoxModel());
box.setEditable(true);
box.getEditor().getEditorComponent().addKeyListener(new KeyListener() {
public void keyPressed(KeyEvent e) {
}
public void keyReleased(KeyEvent e) {
}
public void keyTyped(KeyEvent e) {
// Actual results are retrieved from server via HTTP
box.addItem("Demo");
// Here, the editor window the user was typing in is replaced with the value "Demo".. how to fix this?
}
});
use AutoComplete JComboBox / JTextField,
for listening in JTextComponent is there DocumentListener,
never use KeyListener for Swing JComponents, this listener is designated for AWT Components, for Swing JComponents is there KeyBindings
You need to implement your own MutableComboBoxModel since DefaultComboBoxModel is responsible for the "add item then auto select it" behavior.
I have a GUI designed in Swing with all of the Components laid out. For example I have a JComboBox with a JList and a JTextField,
When I select a different item from the JComboBox I am trying to use a ListSelectionListener to call a method in a subclass to update the JTextField based on the choice,
How would I go about doing that properly? How do I call the subclass and then from the subclass update the GUI object's value?
public class Parent {
private void init() {
// ...
combo.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Object selected = combo.getSelectedItem();
textField.setText(getTextBasedOnSelection(selected));
}
});
// ...
}
/**
* Returns the text to display when the given object is selected.
* Subclasses may override this method to display what they want
*/
protected String getTextBasedOnSelection(Object selected) {
return selected.toString();
}
// ...
}
I hope I get your problem right. You have a View Component with several subviews and you want to update one because of the changes done inside the other one.
Therefore you write an action listener for your combobox in the main View:
comboBox.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent arg0) {
textField.setText(comboBox.getSelectedItem());
}
});
Instead of inter-connecting components directly, I recommend to apply the Mediator pattern:
Create a subclass of JPanel (e.g. XyzPane) where you put all your components in. This class becomes the Mediator. It
listens for events of its components
updates the components as needed
fires its own events, if needed (this allows it to be a part of a parent Mediator: grouping components in Panes and then nesting the Panes)