This week's book giveaway is in the Mac OS forum.
We're giving away four copies of a choice of "Take Control of Upgrading to Yosemite" or "Take Control of Automating Your Mac" and have Joe Kissell on-line!
See this thread for details.
The moose likes Swing / AWT / SWT and the fly likes Tab Key Binding JTextField Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


JavaRanch » Java Forums » Java » Swing / AWT / SWT
Bookmark "Tab Key Binding JTextField" Watch "Tab Key Binding JTextField" New topic
Author

Tab Key Binding JTextField

Will Barbee
Ranch Hand

Joined: Oct 01, 2008
Posts: 41
I have an application with two JTextFields. Data entered into the two JTextFields is then stored
into work fields for SQL update.

The program is working using Action Listener and the Enter key to access the data from the JTextField
and move it into the work fields. But I want to use the tab key to exit from the field and update the data
and also move to the next JTextField.

But my programming for that is not working.

I read the Tutorial on Key binding. I thought it started well but quickly dived too deep and never gave a close
example to my problem. I have read several JavaRanch entries and also their referenced Java topics.
They have been very helpful.

Here are my code examples for one of the two JTextFields:


Changing the data in the JTextField and pressing Enter works.

Changing the data and pressing the Tab key does not. The action code is not processed
because the System.out.println does not print when you press the Tab key.

So obviously I have a programming error or I am missing something.
What is the correct code please?

And would that same code fix work the same if I wanted the Enter key to use the
Key Binding Action processing instead of the Action Listener processing?
Rob Spoor
Sheriff

Joined: Oct 27, 2005
Posts: 19697
    
  20

How about initializing actName before you use it on line 10?


SCJP 1.4 - SCJP 6 - SCWCD 5 - OCEEJBD 6
How To Ask Questions How To Answer Questions
Rob Camick
Ranch Hand

Joined: Jun 13, 2009
Posts: 2191
    
    7
I read the Tutorial on Key binding.


The problem is that the "Tab" and "Shift Tab" are handled by the Focus Subsystem, so you also need to read the section on "How to Use the Focus Subsystem".

Basically you need to use the setFocusTraversalKeys(...) method to either:

a) set the keys to null
b) use the approach the JTable does and just remove the "Tab" key.

Once this is done the Tab key should be handled by your Key Bindings.

If you need further help then you need to create a SSCCE (Short, Self Contained, Compilable and Executable, Example Program), that demonstrates the incorrect behaviour.
Will Barbee
Ranch Hand

Joined: Oct 01, 2008
Posts: 41
I have read How to Use the Focus Subsystem. I have read JTable.
I have looked in numerous places for a way to do it.

Using setFocusTraversalKeys looks promising but I cannot get the code to work.

I tried adding KeyBinding at the JPanel level with an empty Action. That worked fine
but the TAB key quit working entirely. So no good.


I tried the setFocusTraversalKeys using the example in the How to Use the Focus Subsystem but that
gave compile errors "unchecked call to HashSet" on the Set newForwardKeys statement and "unchecked conversion"
on the setFocusTraversalKeys statement.

The <? extends AWTKeyStroke> statement from the Container method definition apparently has to be there also
but I am unclear where it goes. I have tried it in multiple places but get errors that the statement is wrong.

Can anyone give me an example of the correct code to solve my tab problem?

(Give me one good example snippet and I can write one thousand programs.)
Will Barbee
Ranch Hand

Joined: Oct 01, 2008
Posts: 41
Rob Prime,
Yes, the Actions are initialized earlier in the program.
I did not include their code but it was something on the order of:
private Action actName;

Rob Camick
Ranch Hand

Joined: Jun 13, 2009
Posts: 2191
    
    7
(Give me one good example snippet and I can write one thousand programs.)


Or you could actually post a SSCCE showing the problem.

The code worked fine for me.
Rob Spoor
Sheriff

Joined: Oct 27, 2005
Posts: 19697
    
  20

Will Barbee wrote:Rob Prime,
Yes, the Actions are initialized earlier in the program.
I did not include their code but it was something on the order of:
private Action actName;


That's declaring, not initializing. An initialization includes giving the variable a value.
Will Barbee
Ranch Hand

Joined: Oct 01, 2008
Posts: 41
Rob Camick.

As written above, the code causes compile errors "unchecked or unsafe operations".
But the program does run.

However, it turns off the TAB key entirely. With the code as written, the tab key does not
move to the next JTextField (desired result) but it also does not execute the Action defined
for the JTextField (not good).

There's gotta be something I'm missing.

Oh well, as you suggest, I am starting to build a SSCCE.
Will Barbee
Ranch Hand

Joined: Oct 01, 2008
Posts: 41
Rob Prime.

Sorry, missed the intent of your note about initialization.

I moved the Action initializing statements to in front of where the
Actions were used.

There was no change in TAB key behavior.
Will Barbee
Ranch Hand

Joined: Oct 01, 2008
Posts: 41
Okay, here is the SSCCE:

Program 1 - Start-up


And Program 2


Compile with:
javac Tab_Key.java
javac Tab_Go.java

Execute with:
java Tab_Go

The objective is to get the System.out.println's for "Pfm Action XYZ" to print
when the Tab key is pressed after entering data in the JTextFields.

As supplied, the program does not execute the Tab key at all. That, to me, means
that the setFocusTraversalKeys is working - TOO well. And the Actions do not
execute so the println's do not print.

If you comment out the setFocusTraversalKeys at line x thru y then the Tab key works
but the Actions still do not work.

So, what have I missed?

Remember, the original problem is to have some update code work when the tab
key is pressed after entering data into a JTextField. Using the Enter key and Action Event proceesing
does work but clients prefer the Tab key.
Rob Camick
Ranch Hand

Joined: Jun 13, 2009
Posts: 2191
    
    7
In my first reply, I said the problem was with the focus traversal keys, not with the Key Bindings. Yet, in your second posting you changed the code for the Key Bindings for some reason.

So now your code for getting the get KeyStroke is wrong.
Michael Dunn
Ranch Hand

Joined: Jun 09, 2003
Posts: 4632
here's a different approach, fires off an ENTER keyEvent if tab is detected
alternative to new keyEvent is to put the actionListener code (update code) into a separate method,
which can then be called from both the actionListener and the AWTEventListener

but, as I mentioned in your other posting, how are you going to handle someone using the mouse to navigate to the next component?

Rob Spoor
Sheriff

Joined: Oct 27, 2005
Posts: 19697
    
  20

Michael Dunn wrote:

Wouldn't that return the same as System.currentTimeMillis()?
Will Barbee
Ranch Hand

Joined: Oct 01, 2008
Posts: 41
Rob Camick.

I changed the getKeyStroke("TAB") to:

because, in reading through my references, I found that
"the keyCode argument to getKeyStroke should be one of the VK_ virtual key
constants defined by java.awt.event.KeyEvent".

Rob, it would help me more if you would tell me what the correct code is
or an alternative way to write the code. That way I could compare it to my
code and understand the principles better.
Will Barbee
Ranch Hand

Joined: Oct 01, 2008
Posts: 41
Michael Dunn.
Thank you for repeating the point about the mouse.
The FocusGained handles the entrance to a JTextField but does not capture where it came from.
I'll have to think it through.

Thanks also for the alternate coding suggestion. I am beginning to study it now.

Rob Camick
Ranch Hand

Joined: Jun 13, 2009
Posts: 2191
    
    7
because, in reading through my references, I found that "the keyCode argument to getKeyStroke should be one of the VK_ virtual key constants defined by java.awt.event.KeyEvent".


Two things wrong with this:

a) You are not using a VK constant defind in the KeyEvent class. the constants are KeyEvent.VK_A.
b) The reason for that recommendation is that the value of these constants is and int. So it is better to use

new KeyStroke( KeyEvent.VK_A );

than to use:

new KeyStroke( 65 ); // the 65 (if that is the right value) means nothing to anyone looking at the code.

However, if you read the KeyStroke API you will notice that a KeyStroke can be created by using either an int or a String.

Rob, it would help me more if you would tell me what the correct code is


I already told you what the correct code is, I said your original code was correct (regarding the Key Bindings).

Also, the Key Bindings tutorial also had working examples of specfying the KeyStroke using a String.

However, if you really want to use the KeyEvent constants, then you have also seen the proper way to do this in the focus tutorial. The example there uses VK_ENTER.

Or if you are still having problems then you can search the forum or the web using "KeyStroke" as the keyword to find other examples.

We are not here to write every single line of code for you. That is why you where pointed to the tutorials, both of which contained working examples so you could choose the way you prefer to specify the KeyStroke.
Will Barbee
Ranch Hand

Joined: Oct 01, 2008
Posts: 41
Rob Camick.
Thank you. The coding changes are noted. As a "greenhorn", I make many mistakes and always
welcome instructive comments.
Will Barbee
Ranch Hand

Joined: Oct 01, 2008
Posts: 41
Michael Dunn.

Thank you for the AWTEventListener coding.

I studied, compiled and ran it.

It works in the fashion that I need to make my application work.

I have now integrated it into the real program and it works flawlessly.
Will Barbee
Ranch Hand

Joined: Oct 01, 2008
Posts: 41
Michael Dunn.

Your question about mouse navigation:
I have tried a couple of things - one to look for MOUSE_CLICKED the other focusLost.

Neither worked well -
I didn't have the Mouse Listener correct.
As I am using next-JTextField.requestFocus() to navigate, focusLost programming overrides
the mouse clicked action by going to the next JTextField instead of where the mouse is.

At this point, I am goiing to "train the user" while I search for a better programming sequence.
Will Barbee
Ranch Hand

Joined: Oct 01, 2008
Posts: 41
Thank you, JavaRanch
Rob Camick
Ranch Hand

Joined: Jun 13, 2009
Posts: 2191
    
    7
Now that you understand focus management and Key Bindings I question your overall design:

Data entered into the two JTextFields is then stored into work fields for SQL update.

Why do you need "work fields"? When you are ready to do the SQL update you can just do textField.getText() to get the current value. After all you current code is unconditionally saving the text from the text field when you tab out.

But I want to use the tab key to exit from the field and update the data and also move to the next JTextField.


Well, the Tab key already moves to the next text field (assuming you have designed your form properly). So the only change you need is to save the text to your work fields.

As Michael has already suggested, what do you do when the user uses the mouse to click on another text field. The general solution in this case would be to use a FocusListener and just handle the focusLost event. Then the change to you code would be to handle the Enter key with an Action that simply tabs to the next component. Then the FocusListner would update your work variable.

But the problem with this approach is what happens when the user presses the "Update SQL" button, after typing text into a text field. If they have not hit the Enter key, or Tab key or used the mouse the newly typed text has NOT been saved to the work area. Which leads me back to my original suggestion. Just get the text from the text field when you are ready to update the SQL. The code that does this should verify that text has been entered in all text fields before executing the SQL.


Will Barbee
Ranch Hand

Joined: Oct 01, 2008
Posts: 41
Rob Camick.

An interesting approach.

I had wondered if I could use simple tab between fields with no program control.

I will consider using this. I first have to go back and chart each display layout to be
certain that the simple tab will work.

But I will study it in depth.

Thanks, Rob.
Rob Camick
Ranch Hand

Joined: Jun 13, 2009
Posts: 2191
    
    7
I had wondered if I could use simple tab between fields with no program control.


The code in your ActionListener would simply invoke the transferFocus() method of the text field that receive the Enter key.
Will Barbee
Ranch Hand

Joined: Oct 01, 2008
Posts: 41
LESSON LEARNED:
There were several lessons learned here. First the Action processing to kick off an Enter key event
when Tab is pressed works great! But I made the mistake of putting into all my programs. Since I use a
master menu / sub-area menu / processing program approach, the multiple Action processing caused
mulitple events to occur, executing the action code multiple times.

Then, since I was editing data and controlling the cursor to go to the next field if OK or to return to the
origiinal field if error or go elsewhere if OK and certain data was keyed, I found that the tab key as
traversal key and traversal policy were overriding my requestFocusInWindow. So I had to change the
FTP.

To summarize:
1) The following works great to cause Tab key to act like Enter key. BUT it should only be put in the
first executing program (in my case, the sign-on program).


2) But then, to take back control from the Focus Traversal Policy, transfer it to some other key (in this
example, F4) with the following programming. This has to be done for each JFrame.


mayur dhawan
Greenhorn

Joined: Sep 20, 2005
Posts: 29
Hi,
thanks for all the valuable information.
there is another solution I can find for this problem thats to create a FocusAdapter and on Focus lost event just dispatch the ENTER key event.Thus , as soon as person presses tab and the text field looses focus, we can do our computaions as in :





and add this focus listner to the text field as JTextField sample = new JTextField(); sample.addFocusListener(new TestFocusListener());
sample.addActionListener(new ActionListner() ...../* what ever code you want to write*/. )
Rob Spoor
Sheriff

Joined: Oct 27, 2005
Posts: 19697
    
  20

mayur dhawan, please UseCodeTags next time. I've added them for you this time.
 
GeeCON Prague 2014
 
subject: Tab Key Binding JTextField