Right now, when I add a KeyListener to a JTextField, I get an event, then the text updates. But what I need is for the KeyListener to respond after the text is updated. How would I go about doing that? Right now, I am setting a 10-millisecond delay to the response of the KeyListener in another thread, which is sufficient for the text to update and the user to not notice.
Don't use a KeyListener. Swing has newer and better API's than AWT.
Instead you should be adding a DocumentListener to the Document of the JTextfield
A DocumentEvent is generated whenever the Document is updated.
Read the section from the Swing tutorial on How to Write a DocumentListener for more information and examples.
So.... ummmm i know it's kind'a late X)
I kind'a gone around that by using the keyReleased method I noticed that the text gets updated before the key event it should give you something like this
JTextField jtf = new JTextField();
jtf.addKeyaddKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent e) {
// not here
}
#Override
public void keyReleased(KeyEvent e) {
// not here
}
#Override
public void keyPressed(KeyEvent e) {
//do the stuff here
}
});
note that I am not sure why it works but I would think that it has something to do with the typing speed or something, also I am not an expert but i wanted to help (that problem drove me crazy for a couple days) if i am saying any stupid stuff pleas let me know !
Related
Short Version:
How do I determine when a KeyBind key has been released in similar functionality to a KeyListener keyReleased() event?
Long Version:
I am experimenting a bit with making a very simple game, and I was using several KeyListeners to track my keyboard input. However, as I added more complicated features, I began to encounter issues with the keyboard input not receiving proper focus and thus no keyboard input was being received.
Then I read about KeyBinds. While the KeyBinds functionality fixed my focus issue, for my game I was wanting to change a value based off whether a key was pressed or not. I can get the value to change through pressing the key, but I don't know how to detect when the key is released. The KeyListener had a separate KeyPressed and KeyReleased method, but that won't work correctly due to component focusing issues.
Relevant Code:
I don't have a lot of code to share because the input was simply needed to call one of two methods which are set up in another class (and I was testing KeyBinds). But here is the relevant KeyBind code anyway:
Action myAction = new AbstractAction()
{
#Override
public void actionPerformed(ActionEvent e)
{
System.out.println("testing action output");
}
};
actionMap = getActionMap();
inputMap = getInputMap(condition);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "leftArrow");
actionMap.put("leftArrow", myAction);
And here's the code I was using with KeyListener (again, very little since I just call a method)
addKeyListener(new KeyListener()
{
#Override
public void keyPressed(KeyEvent e)
{
racquetClass.keyPressed(e);
}
#Override
public void keyReleased(KeyEvent e)
{
racquetClass.keyReleased(e);
}
#Override
public void keyTyped(KeyEvent e)
{
}
});
Thanks in advance to any and all help that can be provided.
but I don't know how to detect when the key is released.
You need to create a separate Key Binding:
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, true), "leftArrowReleased");
actionMap.put("leftArrowReleased", myReleasedAction);
I want to be able to receive input from the keyboard by the user but I've added everything I thought would allow my program to do this and still it does not work. What am I doing wrong?
class KeyInput implements KeyListener {
public void keyPressed(KeyEvent e) {
System.out.println("keyPressed");
}
public void keyReleased(KeyEvent e) {
System.out.println("keyReleased");
}
public void keyTyped(KeyEvent e) {
System.out.println("keyTyped");
}
}
public GameView() {
this.addKeyListener(new KeyInput());
}
The constructor works fine and KeyInput is an inner class of the GameView object.
When running the game, if I press a key nothing gets printed to the system output.
Am I missing something? Thanks!
KeyListener is fickle mistress, it wants a lot of attention all the time. Basically, it will only raise key events if the component it is registered to has focus AND is focusable.
Generally, you want to avoid using it and use key bindings API instead, How to Use Key Bindings, but this will depend on whether you MUST use pure AWT APIs or not....
I'm developing an application where I want something to be triggered both by the user updating the contents of a JTextArea, or manually via pressing a JButton.
I have done the first part using a DocumentListener and putting the relevant code in its insertUpdate method.
I haven't used Actions before, but I've heard they are useful for situations where you need something to be triggered by multiple controls. Is it possible to trigger the action from the DocumentListener? Is it a good idea to use Actions at all, or should I just put my code in a normal method?
(in the constructor):
textAreaInput.getDocument().addDocumentListener(new DocumentListener() {
public void insertUpdate(DocumentEvent e) {
// do something
}
public void removeUpdate(DocumentEvent e) {}
public void changedUpdate(DocumentEvent e) {}
});
and the Action, which is a field:
Action doSomething = new AbstractAction("Do Something!") {
#Override
public void actionPerformed(ActionEvent e) {
// do it
}
};
clarification:
The JTextArea will receive text that is pasted in by the user, which I want to parse automatically. The parsing depends on other values set elsewhere in the GUI; if the user changes these other values, he may want to re-parse the text, hence the need to perform the same action by pressing a button.
I want something to be triggered both by the user updating the contents of a JTextArea, or manually via pressing a JButton.
This doesn't make sense to me.
Why would clicking a button invoke the same Action as a user typing text into a text area?
I haven't used Actions before, but I've heard they are useful for situations where you need something to be triggered by multiple controls
That statement is meant for controls that the user clicks, like JMenuItems, JButtons or hitting Enter on a text field. In general they can be used when you use an ActionListner.
A DocumentListener is not an ActionListener so as I stated earlier the use of an Action doesn't seem appropriate.
I think you need to clarify your requirement.
Edit, based on clarification
if the user changes these other values, he may want to re-parse the text
Why does the user have a choice? If you change the font, text, foreground, background of a text area, the component it automatically repainting, you don't have to ask for this to be done. If you look at the code for these methods they always end up invoking the revalidate() and repaint() methods.
The parsing depends on other values set elsewhere in the GUI;
Sounds like you need a custom class. Maybe a ParsedTextArea or ParsedDocument. This class would contain the "properties" that can be set elsewhere in the GUI. It would implmenent the DocumentListener. It would also support your "parseTheText" method. So whenever a property is changed or a DocumentEvent is generated you automatically invoked the "parseTheText" method. This way you don't need a separate button and the component will always be in sync because the parsing is automatic.
You can invoke the actionPerformed() method, whether it's in an Action or not. There's an example here.
I think you need not create the Action object. You can add ActionListener to the Button just like you have added DocumentListener to the Document of the input. If I correctly understand your problem, may be you should do something like this:
textInput.getDocument().addDocumentListener(new DocumentListener(){
#Override
public void insertUpdate(DocumentEvent e) {
doIt();
}
#Override
public void removeUpdate(DocumentEvent e) {}
#Override
public void changedUpdate(DocumentEvent e) {}
});
button.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
doIt();
}
});
doIt() is a method in which you will do what you wanted to do.
im trying to get the cursor to move to a textfield when a specific key is pressed like when you press tab. im trying to do this instead of just using tab because i want to implement other actions at the same time, how do i do this?
here is the key event for keypressed so far
Fname.addKeyListener(new KeyListener(){
#Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
if(e.getKeyCode() == KeyEvent.VK_TAB){
Sname.setFocusable(true);
Sname.getFocusAccelerator();
if(Sname.hasFocus()){
Sname.setText("");
}
}
//System.out.print(e + "keyRelease: ");
}
any help would be greatly appreciated thank you for your time
i want to implement other actions at the same time
Don't use a KeyListener. Swing was designed to use Key Bindings.
See Key Bindings for more information and a link to the Swing tutorial on the same topic.
I'm currently trying to receive key events during a drag and drop, but it seems to me that the focus is taken away while dragging so that I can't listen to any key events.
I'm dragging a JComponent subclass that implements KeyListener and requests the focus in the DragSourceListener's dragEnter method, but my assumption is that the focus is taken away from it afterwards.
Now, who's got the focus and how can I take it away back to my JComponent. Or is there a different approach that is more suitable for dnd?
Thank you in advance.
UPDATE:
It's a lot of code necessary to make this work so I'm only going to post some snippets to show you what I'm trying to do:
public class Stone extends JComponent implements Serializable, KeyListener {
public Stone(...) {
//...
setFocusable(true);
addKeyListener(this);
this.dragSource = DragSource.getDefaultDragSource();
this.dgListener = new StoneDGListener();
this.dsListener = new StoneDSListener();
this.dragSource.createDefaultDragGestureRecognizer(
this,
DnDConstants.ACTION_MOVE,
this.dgListener
);
//...
}
//...
public void keyPressed(KeyEvent e) {
System.out.println("Stone: "+e.getKeyCode());
}
//...
public class StoneDSListener implements DragSourceListener, Serializable {
//...
#Override
public void dragEnter(DragSourceDragEvent dsde) {
//...
Stone.this.requestFocus();
addKeyListener(Stone.this);
}
//...
}
}
What happens is that before I'm dragging the Stone component my JPanel has the focus so it receives any keys I'm pressing.
During the drag I can't listen to any pressed keys(so I don't know who's got the focus) even though I'm requesting it when in dragEnter() and after I release the Stone any key events are send to the Stone.
It's probably not important for the question but to illustrate what I'm doing here's a screenshot:
image showing the "drag" http://img685.imageshack.us/img685/1884/pico.png
(Here I'm dragging the Stone from the collection below to the game field on the top). In this state I don't know how to find out what keys are pressed. I need to figure this out in order to be able to rotate the Stone.
Not sure who has focus during a drag and drop. But an alternative solution to your problem would be to add a KeyEventDispatcher for your Stone class to the KeyboardFocusManager. From the JavaDoc:
The KeyboardFocusManager is both a centralized location for client code to query for the focus owner and initiate focus changes, and an event dispatcher for all FocusEvents, WindowEvents related to focus, and KeyEvents+.
+ my emphasis.
Basically we use similar sort of code to intercept KeyEvents before they hit the Component that has focus.
Just gave it a quick test for your particular drag and drop context and it seems to work alright (as long as your application has focus within the operating system). Essentially something along the lines of:
Public Stone(...) {
// ...
KeyboardFocusManager fm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
fm.addKeyEventDispatcher(
new KeyEventDispatcher() {
public boolean dispatchKeyEvent(KeyEvent e) {
System.out.println("Key Press: " + e.getKeyChar());
return false;
}
}
);
// ...
}
You will need to do a bit of leg-work on enabling and disabling when the user is no longer dragging and dropping as my test currently prints all the time.
I also wonder if it is possible to use the KeyboardFocusManager to determine who actually ends up with focus during a drag and drop?
Anyway, I hope this gives you a few new ideas to try.