Phil Whittaker
Phil Whittaker

Reputation: 81

Get caret position when key pressed using KeyboardFocusManager

I'm trying to get the current caret position when the "<" character is typed, using a KeyboardFocusManager. Code below. If the text field is empty when they character is typed I would expect the caret position to be 0. However, the result I actually get is this: 0 0 1. Could anyone explain why this is happening?

import java.awt.KeyEventDispatcher;
import java.awt.KeyboardFocusManager;
import java.awt.event.KeyEvent;

import javax.swing.*;


public class TextEditor {

    @SuppressWarnings("serial")
    public static class TextClass extends JTextArea {

        static int startpos = 0; 

        public boolean checkKeyTyped (KeyEvent e) {
            String keystr = Character.toString(e.getKeyChar());
            switch (keystr) {
                case "<":
                    startpos = getSelectionStart();
                    System.out.print("   " + startpos);
            }
            return false;
        }
    }       

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(300, 200);
        frame.setLocationRelativeTo(null);
        final JTextArea textArea = new TextClass();
        frame.add(textArea);
        frame.setVisible(true);

        // Add keyboard listener

        KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(new KeyEventDispatcher() {
            public boolean dispatchKeyEvent(KeyEvent e) {
                return ((TextClass) textArea).checkKeyTyped(e);
            }
        });
    }
}

Upvotes: 2

Views: 592

Answers (2)

Nicolas Filotto
Nicolas Filotto

Reputation: 44995

It is not how you are supposed to do it, you are supposed to implement a KeyListener and add it to your JTextArea using addKeyListener(KeyListener), as next:

final JTextArea textArea = new TextClass();
...
textArea.addKeyListener(new KeyListener() {
    @Override
    public void keyTyped(final KeyEvent e) {
        char key = e.getKeyChar();
        switch (key) {
            case '<':
                System.out.print("   " + textArea.getSelectionStart());
        }
    }

    @Override
    public void keyPressed(final KeyEvent e) {
    }

    @Override
    public void keyReleased(final KeyEvent e) {
    }
});

Up to now, you get it printed 3 times because your method is called for each type of KeyEvent that is triggered whenever you type on a key:

KEY_TYPED

The "key typed" event. This event is generated when a character is entered. In the simplest case, it is produced by a single key press. Often, however, characters are produced by series of key presses, and the mapping from key pressed events to key typed events may be many-to-one or many-to-many.

KEY_PRESSED

The "key pressed" event. This event is generated when a key is pushed down.

KEY_RELEASED

The "key released" event. This event is generated when a key is let up.

Upvotes: 0

Tamas Rev
Tamas Rev

Reputation: 7166

You are using a general Key Event dispatcher. The possible events are KEY_PRESSED, KEY_TYPED and KEY_RELEASED. Based on what you say, you need KEY_TYPED. So filter for that:

KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(new KeyEventDispatcher() {
        public boolean dispatchKeyEvent(KeyEvent e) {
            if (e.getKeyCode() == KeyEvent.KEY_TYPED) {
                return ((TextClass) textArea).checkKeyTyped(e);
            }
        }
    });

Upvotes: 0

Related Questions