Java KeyListener not firing on JSpinner
Asked Answered
C

3

5

have tried a few different approaches to this but with no success so far. Just wondered if I'm missing anything. I have a JSpinner which is a component of a DateSelector widget alongside a Calendar. I am trying to fire a validation method if the user changes any text in the JSpinner instead of using the Calendar control or the JSpinner up and down arrows.

Here are the different approaches I have tried:

jSpinner1.addKeyListener(kl);

jSpinner1.getEditor().addKeyListener(kl);

((JSpinner.DefaultEditor) jSpinner1.getEditor().getTextField().addKeyListener(kl);

Anyone out there got any ideas as to what I'm doing wrong? Thanks

UPDATE Apologies, I should have said that I have already added a ChangeListener to the JSpinnerDateModel which is attached to the JSpinner. Like so:

ChangeListener changeListener = new ChangeListener() {
        @Override
        public void stateChanged(ChangeEvent e) {
            dateChanged();
        }
    };

    jSpinnerDateModel.addChangeListener(changeListener);

    KeyListener keyListener = new KeyListener() {

        @Override
        public void keyTyped(KeyEvent e) {
            // TODO Auto-generated method stub

        }

        @Override
        public void keyPressed(KeyEvent e) {
            System.out.println(e.getKeyChar());
            dateChanged();
        }

        @Override
        public void keyReleased(KeyEvent e) {
            // TODO Auto-generated method stub

        }

    };
    ((JSpinner.DefaultEditor) jSpinner1.getEditor()).getTextField().addKeyListener(
            keyListener);

Thanks

Frank

Camey answered 6/10, 2010 at 15:0 Comment(0)
C
2

JSpinners handle KeyEvents themselves, but they fire ChangeEvents to the outside world. Adding a ChangeListener should allow you to perform the validation you wish.

See also: Detecting Spinner Value Changes (Java Tutorials)

Cardcarrying answered 6/10, 2010 at 15:10 Comment(5)
Apologies for not including this info in the original question (I have update it now) but I already have a ChangeListener attached to the Model of the JSpinner. This catches any changes made to the value in the JSpinner but only if the user uses the JSpinner controls. I am trying to fire the key pressed event of a KeyListener for when the user manually edits the value of the JSpinner via the keyboard. ThanksCamey
@Frank: A ChangeListener should fire whenever the user changes the value and focuses away (or presses Enter). You're right that it won't fire while the user is typing, though.Cardcarrying
Yeah that's the issue I'm having. This is part of a wizard panel and if the user simply selects a date and clicks next then the focus is not lost and the validation method fires too late. Thanks for your input anyway. Seems to be trickier than first thought.Camey
@Frank: I just tried the KeyListener code you posted and I saw events printed out every time I changed the text of my spinner. Do you just get nothing?Cardcarrying
Really? My ChangeListener is firing fine but if I focus on the Textfield of the JSpinner and edit the value by hand I get nothing. I have breakpointed all key events and it triggers none of them. No output. How can you be successful with the same code? It must be something else... Only way it can make sense if yours works. Thanks I'll keep trying different things.Camey
G
14

If you want to disable keyboard editing do this:

JFormattedTextField tf = ((JSpinner.DefaultEditor)spinner.getEditor()).getTextField();
tf.setEditable(false);

To listen for key events you need to add a listener to the text field. This works for me:

((JSpinner.DefaultEditor)spinner.getEditor()).getTextField().addKeyListener(new KeyListener(){

            @Override
            public void keyPressed(KeyEvent e) {                    
            }

            @Override
            public void keyReleased(KeyEvent e) {
                System.out.println("PRESSED!");                    
            }

            @Override
            public void keyTyped(KeyEvent e) {                    
            }

        });
Gamber answered 6/10, 2010 at 15:5 Comment(2)
Yeah thanks for this. I have this as a last option if I have to but I would rather the user had full access to edit the date using the controls or manually via the keyboard.Camey
Thanks but I already had this code in place - I have updated the question to show all the code in use. Sorry about that.Camey
C
2

JSpinners handle KeyEvents themselves, but they fire ChangeEvents to the outside world. Adding a ChangeListener should allow you to perform the validation you wish.

See also: Detecting Spinner Value Changes (Java Tutorials)

Cardcarrying answered 6/10, 2010 at 15:10 Comment(5)
Apologies for not including this info in the original question (I have update it now) but I already have a ChangeListener attached to the Model of the JSpinner. This catches any changes made to the value in the JSpinner but only if the user uses the JSpinner controls. I am trying to fire the key pressed event of a KeyListener for when the user manually edits the value of the JSpinner via the keyboard. ThanksCamey
@Frank: A ChangeListener should fire whenever the user changes the value and focuses away (or presses Enter). You're right that it won't fire while the user is typing, though.Cardcarrying
Yeah that's the issue I'm having. This is part of a wizard panel and if the user simply selects a date and clicks next then the focus is not lost and the validation method fires too late. Thanks for your input anyway. Seems to be trickier than first thought.Camey
@Frank: I just tried the KeyListener code you posted and I saw events printed out every time I changed the text of my spinner. Do you just get nothing?Cardcarrying
Really? My ChangeListener is firing fine but if I focus on the Textfield of the JSpinner and edit the value by hand I get nothing. I have breakpointed all key events and it triggers none of them. No output. How can you be successful with the same code? It must be something else... Only way it can make sense if yours works. Thanks I'll keep trying different things.Camey
S
2

This is a shortfall of swing, and in my opinion JSpinner should follow JComboBox in supplying the following access to the underlying text field:

JComboBox.getEditor().getEditorComponent()

From going through the source of J1.7 I found you can acheive pretty much the same thing with

JSpinner.getEditor().getComponent(0)

Therefore you can "hack" the listener in the following way:

JSpinner.getEditor().getComponent(0).addKeyListener(...)

Obviously this depends on the 'under the covers' implementation of swing and works as at J1.7 but there is no guarantee this works for other versions future or past.

Enjoy.

EDIT

or if the editor is an instance of DefaultEditor, you can cast it as such and use 'getTextField()'. It would be handy if this were defined in the interface.

Seta answered 9/4, 2013 at 23:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.