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();
}
});
Related
I'm actually started learning about javax.swing for graphics. For event listening like KeyListener, MouseListener etc., I have to implement all their methods with their own headers.
I previously worked in JS, and there event listening is very simple.
So I decided to create my own class myButton which extends JButton and also implements all the listeners required. But the statements for what has to be done when the button is clicked should be placed in mouseClicked normally, but using that externally I'm not getting how to use that. Another thing is that I want to create a method onClick inside myButton class which has the parameter of the function name same as JS. But I don't know how to create that function. Moreover function passing is not there in Java. And another problem is that how can I tell the program the onClick method is the method that should be implement when the button is clicked.
So these are the two things I wanted to clarify and know how to achieve them.
Use my own method (onClick) instead of the default (mouseClicked).
How to pass a function name or an anonymous function (which should actually be implemented) as an argument to the onClick method as it is in Javascript.
Thanks in advance
Seriously, I think you need to go and read How to Use Buttons, Check Boxes, and Radio Buttons and How to Write an Action Listener which will ultimately do what you want
So something like...
JButton btn = new JButton("Click me");
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("I was clicked");
}
});
will do exactly what you've just described. The fact is, most components already have some mouse and/or keyboard controls built in, so you don't "have" to reinvent the whole wheel over again.
So I decided to create my own class myButton which extends JButton and also implements all the listeners required. But the statements for what has to be done when the button is clicked should be placed in mouseClicked normally, but using that externally I'm not getting how to use that.
Yes this is what a custom interface would be used for - but the question is, is it important for the button to generate events when a "mouse" action occurs as to apposed to a "key board" action or some other action?
This is why the ActionListener is generally used, as it provides an agnostic event handler for when the button is "actioned", generally, regardless of how it was triggered
Another thing is that I want to create a method onClick inside myButton class which has the parameter of the function name same as JS. But I don't know how to create that function. Moreover function passing is not there in Java. And another problem is that how can I tell the program the onClick method is the method that should be implement when the button is clicked.
There are no functions in Java, just objects. This is where an interface would be useful, it's a contract which describes what functionality an implementation is expected to provide.
You've already used them, you just need to define what your expected "trigger"/method/callback will be for your "onClick" action.
Ok but I want the button to listener for more events like hover, drag etc.
Well drag'n'drop is handled by the Drag and Drop and Data Transfer API and is, again, designed to provide an agnostic and re-usable workflow for what is, honestly, a very complicated feature.
And using actionListener might be useless for that moreover I'm keeping different responses for different kinds of events .
No, but you could use the ButtonModel instead, for example...
btn.getModel().addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
if (btn.getModel().isRollover()) {
System.out.println("You have entered the spiders web");
} else {
System.out.println("You have escaped");
}
}
});
btn.setRolloverEnabled(true);
(note - the JButton can also support "roll over" images automatically)
Or if you just wanted to display a tooltip you could just use...
btn.setToolTipText("What are you waiting for");
And if you wanted some custom keyboard action, you could make use of the Key Bindings API, for example...
InputMap im = btn.getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap am = btn.getActionMap();
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_M, InputEvent.ALT_DOWN_MASK), "pressed");
am.put("pressed", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("Activiated via the keyboard");
JButton btn = (JButton) e.getSource();
btn.doClick();
}
});
I would also recommend having a look at Introduction to Event Listeners.
Now, if you're really hell bent on making your own button, then JButton really isn't the place to get started. You'd want to look at ButtonUI and look and feel APIs, but this is a really advance level of Swing and to be honest, not many seasoned developers get down to this level.
But what about MouseWheel?
Why would need to do anything other than add a MouseWheelListener to an existing instance of JButton? What "extra" functionality do you intend to provide which wouldn't need to be delegated to another listener?
Sure, maybe you could use it as means to increase or decrease a counter I guess, but then, I'd probably only be using a seperate MouseWheelListener anyway, it's not a feature that I'd consider useful on a regular bases ... in fact, I can't say I've ever used these two together.
Theres a general concept in OO, "prefer composition over inheritance", you might want to become familiar study up on it.
Runnable example...
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
JButton btn = new JButton("Click me");
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("I was clicked");
}
});
btn.getModel().addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
if (btn.getModel().isRollover()) {
System.out.println("You have entered the spiders web");
} else {
System.out.println("You have escaped");
}
}
});
btn.setRolloverEnabled(true);
btn.setMnemonic('m');
InputMap im = btn.getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap am = btn.getActionMap();
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_M, InputEvent.ALT_DOWN_MASK), "pressed");
am.put("pressed", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("Activiated via the keyboard");
JButton btn = (JButton) e.getSource();
btn.doClick();
}
});
btn.setToolTipText("What are you waiting for");
btn.addMouseWheelListener(new MouseWheelListener() {
#Override
public void mouseWheelMoved(MouseWheelEvent e) {
System.out.println("I've been wheeled");
}
});
add(btn);
}
}
}
Please, understand, I'm not suggesting that you "can't" do all the things you're trying to do, what I'm trying to suggest is, first figure out "how" those things might be done already, then explore which ones do and don't work for you. From there you can start exploring alternative workflows.
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.
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.
I'm trying to get a simple JFrame with a single button to fire an event when any of these events happen:
The Enter key is pressed AND the JButton has focus
The Spacebar is pressed AND the JButton has focus
The JButton is clicked.
It seems that the Enter and Spacebar come "for free" along with the default mouse click using addActionListener on the JButton; trouble is, I've read that the the key bindings are dependent on the Look and Feel used.
I've tried to get universal behavior across LaF by adding Enter and Spacebar to the JButton's action map, and even added a random key ("m") to make sure the ActionMap was doing the work (it was), but now the mouse click is lost. The only way I seem to be able to get all the keys and mouse click is to use both action map and addActionListener.
Is there a way to get these key and mouse bindings to work consistently across all LaF without trying to detect every possible LaF that may come along? Can I register a single action listener that will fire on both key and mouse events?
My favorite solution would be to add a mouse click to the JButton action map and detect which key or mouse click happened inside the inside the action.
I'm still learning the ropes here, so this probably isn't the best or most efficient way to do things; I'm sure it's over-engineered. This is sort of training exercise where I'm experimenting with everything I can get my hands on. Any and all coding style comments are welcome!
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
public class Example extends JFrame {
// ============================
private class BtnListener extends AbstractAction {
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent ae) {
System.out.println("\nclick button listener triggered");
System.out.println(ae.getSource().getClass().toString());
}
} // class BtnListener
private static final int NO_MODIFIER = 0;
private static final boolean ON_KEY_PRESS = false;
private static final KeyStroke ENTER_PRESSED = KeyStroke.getKeyStroke(
KeyEvent.VK_ENTER, NO_MODIFIER, ON_KEY_PRESS);
private static final KeyStroke M_PRESSED = KeyStroke.getKeyStroke(
KeyEvent.VK_M, NO_MODIFIER, ON_KEY_PRESS);
private static final KeyStroke SPACEBAR_PRESSED = KeyStroke.getKeyStroke(
KeyEvent.VK_SPACE, NO_MODIFIER, ON_KEY_PRESS);
private JButton btnButton;
private final AbstractAction btnListener = new BtnListener();
private JPanel buttonPanel;
private JFrame frmMain;
public static void main(String[] args) {
Example ex = new Example();
ex.displayFrame();
}
Action btnActionListener = new AbstractAction() {
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
System.out.println("\nkey button action triggerred");
System.out.println(e.getSource().getClass().toString());
if (e.getSource() instanceof JButton) {
System.out.println("button");
} else {
System.out.println("Something else");
}
}
};
public Example() {
initialize();
}
public void displayFrame() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Throwable e) {
e.printStackTrace();
}
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
frmMain.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
private void initialize() {
frmMain = new JFrame();
btnButton = new JButton("Abutton");
// Comment this out, you lose the mouse click
btnButton.addActionListener(btnListener);
// Comment out ActionMaps, but keep addActionListner (above), and
// only lose M_PRESSED
InputMap buttonFocusedMap = btnButton
.getInputMap(JComponent.WHEN_FOCUSED);
buttonFocusedMap.put(ENTER_PRESSED, "blah");
btnButton.getActionMap().put("blah", btnActionListener);
buttonFocusedMap.put(SPACEBAR_PRESSED, "blort");
btnButton.getActionMap().put("blort", btnActionListener);
buttonFocusedMap.put(M_PRESSED, "gaaak");
btnButton.getActionMap().put("gaaak", btnActionListener);
// Is there a way to add a mouse click to the ActionMap?
buttonPanel = new JPanel();
buttonPanel.add(btnButton);
frmMain.getContentPane().add(buttonPanel);
frmMain.setBounds(100, 100, 500, 432);
frmMain.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
BasicButtonListener, used by BasicButtonUI, ensures that all buttons (check, radio, toggle) are bound to Space when focused. This works across platforms, even though individual Look & Feels may render various button model states uniquely. Pressing Space evokes the pressed UIAction, and releasing Space evokes the released UIAction. The same occurs when the mouse is pressed and released within the button's bounds; drag outside the button while pressed to see the armed state change.
In either case, the combination of pressed and released invokes your button's actionPerformed() method.
One convenient way to bind Enter to an Action, irrespective of focus, is via the root pane's setDefaultButton() method. This example illustrates all three ways to click a button.
What you can (and probably should) do is create an AbstractAction. You can use the AbstractAction both for your ActionMap as well as for clicking (do JButton.setAction(...))
I'm puzzled as to why a JTextField doesn't seem to just "clear out" by using the setText("") method on it, when this is coming from a KeyListener. It works fine from an ActionListener, except that, most amazingly, if the KeyListener method tries to invoke the ActionListener method, with a dummy action event (created on the fly as a simple test), it still leaves the typed text in place.
In other words, when you run it from the command line, if you type, for example, a "3" into the field, you will see the setText("test") method does not wipe out the 3, as I would expect and desire, but rather leaves it in place. You will then see "test3" in the display. I have noted this line with a comment. Clicking the JButton will wipe out the text properly. The JButton and JLabel will change text properly. but the JTextField won't. If you then press the button, you will see that the action event clears out the JTextField properly. Now, if you toggle the commented out line, you can see an attempt to invoke the actionPerformed method from the KeyTyped method!!! And still, when you type a "3" into the text field, it will not get wiped out. I would expect the setText("") method to clear it out, which it won't. And this is even when the keyTyped() method is invoking the same actionPerformed() method as the JTextButton.
Motivation here may help a little. I have a need to trap one particular hot-key which will clear out the JTextField at the moment it is typed, just as if you pressed the "clear" button. And this doesn't seem to work.
I haven't done that much with Swing before, but this is quite puzzling.
My SSCCE code follows:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
class P2 implements KeyListener, ActionListener
{
JTextField fld;
JButton btn;
JLabel lbl;
P2()
{
JFrame frm = new JFrame("Test");
fld = new JTextField(10);
JPanel pnl = new JPanel();
btn = new JButton("Clear it out");
lbl = new JLabel("This is a test");
fld.addKeyListener(this);
btn.addActionListener(this);
frm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frm.setSize(400,400);
frm.setLayout(new FlowLayout() );
pnl.add(fld);
pnl.add(btn);
pnl.add(lbl);
frm.getContentPane().add(pnl);
frm.setVisible(true);
}
public void keyPressed(KeyEvent ke) {}
public void keyReleased(KeyEvent ke) {}
public void keyTyped(KeyEvent ke)
{
System.out.println("got a pressed key");
//this is the setText method that ought to wipe clean the field comments:
this.fld.setText("test");
this.btn.setText("try again");
this.lbl.setText("got a presseed key");
//toggle this comment to see the invocation of the action event:
// this.actionPerformed(new ActionEvent( new Object(), 2, "test") );
}
public void actionPerformed(ActionEvent ae)
{
fld.setText("");
fld.selectAll();
}
public static void main(String[] args)
{
SwingUtilities.invokeLater
(
new Runnable()
{
public void run()
{
new P2();
}
}
);
}
}
This behavior is due to the fact that the KeyEvent will be processed by the field after your KeyListener was fired. You can circumvent it by consuming the event via
ke.consume();
inside your method keyTyped.
Depending on your requirements another way would be to encapsulate the clearing calls inside a SwingUtilities.invokeLater which will be processed after your current event and thus clear the field after it was updated.
Here's a code snippet using key bindings to wipe out all text on pressing 'a', implemented to use actions already registered in the field's action map (note that you still need to wrap the code into SwingUtilities.invokeLater - as Howard already suggested - that guarantees it to be processed after the fields internal processing)
JTextField normal = new JTextField("just a normal field", 10);
final Action selectAll = normal.getActionMap().get("select-all");
final Action cut = normal.getActionMap().get("cut-to-clipboard");
Action combine = new AbstractAction() {
#Override
public void actionPerformed(final ActionEvent e) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
selectAll.actionPerformed(e);
cut.actionPerformed(e);
}
});
}
};
normal.getActionMap().put("magic-delete-all", combine);
normal.getInputMap().put(KeyStroke.getKeyStroke("A"), "magic-delete-all");