JTextComponent Keymap
Asked Answered
L

2

6

I need to create a class derived from JTextComponent (from JTextPane, actually) in which at least one of the default key mappings is changed. That is, in my special JTextPane, I want the ">" keystroke to perform an action and NOT add that character to the text pane as, by default all printable typed characters are treated.

To defeat the normal behavior, there are the following APIs:

  • JTextComponent.getKeymap()
  • Keymap.addActionForKeyStroke()
  • JTextComponent.setKeymap()

However, I find that though these methods are not static they DO affect the keymap used by all JTextComponents in my application. There is no simple mechanism by which a Keymap may be cloned which, presumably would solve the problem, or am I missing something.

What I am after is a way to change the keymap for my JTextPane class but not for ALL JTextComponent-derived classes.

Or should I be looking elsewhere?

Locution answered 15/8, 2012 at 16:24 Comment(1)
This is an awesome question, really well done. While it doesn't answer question directly, take a look #9610886 for an example of what others have done with a similar situation. aymeric is on the right trackMalta
L
7

IMHO, aIt's a bit difficult to understand but the answer is here: Using the Swing Text Package by Tim Prinzing

The author of the article, Tim Prinzing, who is also, I believe, the author of JTextComponent according to source code, provides an example which I will comment:

      JTextField field = new JTextField();
// get the keymap which will be the static default "look and feel" keymap
      Keymap laf = field.getKeymap();
// create a new keymap whose parent is the look and feel keymap
      Keymap myMap = JTextComponent.addKeymap(null, laf);
// at this point, add keystrokes you want to map to myMap
      myMap.addActionForKeyStroke(getKeyStroke(VK_PERIOD, SHIFT_DOWN_MASK), myAction); 
// make this the keymap for this component only.  Will "include" the default keymap
      field.setKeymap(myMap);

My mistake was adding my keystroke to the keymap returned by getKeymap instead of letting it to the child. IMHO, the name addKeymap() is confusing. It should probably be createKeymap().

Locution answered 15/8, 2012 at 18:25 Comment(3)
But, but, but ... I would have thought that when my key is pressed, and the key processing (see diagram in above mentioned article) finds my keystroke and executes the action (this part works fine), that it would CONSUME the key event. This does not happen! Instead, it also prints it on the screen. I can see that the event is still alive by logging in a Key Listener. However, all I get iin my action is an ActionEvent, which cannot be consumed!Locution
The link is rotten and cannot be followed. As you did not write a name of the page or anything like that, I do not know how to search for it. Do you think you could find the page new location, or remember how the page was named?Qintar
@Qintar - it wasn't easy but I found the thing to Google: "myMap Prinzing". That led me to comp.nus.edu.sg/~cs3283/ftp/Java/swingConnect/text/text/… . And the title of the article is "Using the Swing Text Package". Can't find any other copies of it. Looks like Oracle got rid of it.Locution
A
4

I would go for a specific Document instead, especially if you want your mapping to be valid just for an instance and not globally.

Here is an example of capturing keys and perform appropriate actions:

JFrame f = new JFrame();

StyledDocument d = new DefaultStyledDocument() {
   @Override
   public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
      if (">".equals(str)) {
         // Do some action
         System.out.println("Run action corresponding to '" + str + "'");
      } else {
         super.insertString(offs, str, a);
      }
   }
};

JTextPane t = new JTextPane(d);
f.add(t);
Autograph answered 15/8, 2012 at 20:35 Comment(1)
I'd use a personally use a DocumentFilter, but I think you're on the right track. I'm, personally, a little concerned about attaching some kind of action to the filter, but that's just me ;)Malta

© 2022 - 2024 — McMap. All rights reserved.