Results 1 to 12 of 12
Thread: KeyMap/ActionMap question
- 01-24-2011, 08:57 AM #1
- Join Date
- Sep 2008
- Location
- Voorschoten, the Netherlands
- Posts
- 11,408
- Blog Entries
- 7
- Rep Power
- 17
KeyMap/ActionMap question
Greetings,
I though I knew how KeyMaps and ActionMaps work; obviously I don't ... Suppose I want to track what a user has typed in a JTextArea. I change the default action in the KeyMap and make it point to my Action. All works fine. Also suppose I don't want the user to type, say, the up arrow key. I defined an Action that does nothing:
And set the entry DefaultEditorKit.upAction to this action in the ActionMap of the JTextArea. The up-arrow key still works ... Also, I thought that the entryJava Code:private static final Action ignoreAction= new AbstractAction() { public void actionPerformed(ActionEvent ae) { } };
DefaultEditorKit.deletePrevCharAction was called when the user pressed the backspace key, but that doesn't happen: my default handler Action is called when that key is pressed. My class is a total mess now, there's debug code all over the place but I hope the above description is clear. How do I forbid certain characters to be typed and how do I change the Actions associated with action names (they're all Strings, see the DefaultEditorKit class). Basically I want to track what the user is typing in a JTextArea and only the forward/backward keys, delete current and previous keys are supposed to work (and all ordinary keys of course, plus the enter key).
I have a love/hate relationship with Swing; the love relationship shows up when I see Camickr or Darry Burke play with it; the hate relationship rears its ugly head when I put my fingers on it. ;-)
kind regards,
JosWhen people rob a bank they get a penalty; when banks rob people they get a bonus.
- 01-24-2011, 03:55 PM #2
Moderator
- Join Date
- Jul 2010
- Location
- California
- Posts
- 1,609
- Rep Power
- 5
I recently was going through something similar and feel your pain. Have you tried removing the actions from all the maps (or a combination of them - WHEN_FOCUSED, WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, and WHEN_IN_FOCUSED_WINDOW)?
Last edited by doWhile; 01-24-2011 at 03:57 PM.
- 01-24-2011, 04:01 PM #3
- Join Date
- Sep 2008
- Location
- Voorschoten, the Netherlands
- Posts
- 11,408
- Blog Entries
- 7
- Rep Power
- 17
- 01-24-2011, 04:14 PM #4
- Join Date
- Sep 2008
- Location
- Voorschoten, the Netherlands
- Posts
- 11,408
- Blog Entries
- 7
- Rep Power
- 17
No, that doesn't work; I have a WrapperAction class that wraps another Action, does what it has to do and calls the actionPerformed( ... ) method on the wrapped class. I populate my own ActionMap with all the WrapperActions and set that map to the JTextArea. The parent of my map is set as the original Map delivered by the JTextArea; I clear out all parents of my map. My thoughts are/were that my Actions are called, my WrapperAction does what it has to do and calls the original (now wrapped) Action. Now none of the wrapped Actions work anymore. It's back to the drawing board for me ;-)
kind regards,
JosWhen people rob a bank they get a penalty; when banks rob people they get a bonus.
- 01-24-2011, 05:34 PM #5
Moderator
- Join Date
- Jul 2010
- Location
- California
- Posts
- 1,609
- Rep Power
- 5
Is it possible to provide an SSCCE to work with? I'll post an example snippet below which removes the key bindings - with this code all keys (except characters) are removed and do not work. Take this with a grain of salt, because I don't have time at the moment to read through the API's and determine if this is the correct way to go about doing this (and as a result seems like a crude hack to me), but when played with a bit it demonstrates the parent ActionMap's participate
Java Code:public static void main(String args[]){ JFrame frame = new JFrame(); JTextArea text = new JTextArea(); text.setText("Testing 123"); text.getInputMap().clear(); ActionMap map = text.getActionMap(); ActionMap parent = map.getParent(); while ( parent != null ){ parent.clear(); parent = parent.getParent(); } JScrollPane scroller = new JScrollPane(text); scroller.setPreferredSize(new Dimension(400,500)); frame.getContentPane().add(scroller); frame.pack(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); }
- 01-24-2011, 06:19 PM #6
- Join Date
- Sep 2008
- Location
- Voorschoten, the Netherlands
- Posts
- 11,408
- Blog Entries
- 7
- Rep Power
- 17
I did exactly the same: clear out all parent maps. Below you'll find the class I've been struggling with most of this morning. Drop one S from the SSCE but it is fairly self contained: create one given a JTextArea and see what is written on stderr. Here's the code:
The code started off as fairly simple but, as you can see, the default key typed class contains code that it shouldn't contain (imho) because I expected other Action classes to handle it. I'm sort of lost on this stuff ...Java Code:package com.dadid.utils.gui; import java.awt.event.ActionEvent; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.ActionMap; import javax.swing.JTextArea; import javax.swing.text.DefaultEditorKit; public class TextInputStream { private static final Object[] ignores = { DefaultEditorKit.beginAction, DefaultEditorKit.beginLineAction, DefaultEditorKit.upAction, DefaultEditorKit.downAction, DefaultEditorKit.endAction, DefaultEditorKit.endLineAction, DefaultEditorKit.nextWordAction, DefaultEditorKit.previousWordAction, DefaultEditorKit.pageDownAction, DefaultEditorKit.pageUpAction, DefaultEditorKit.selectAllAction, DefaultEditorKit.selectionBackwardAction, DefaultEditorKit.selectionBeginAction, DefaultEditorKit.selectionBeginLineAction, DefaultEditorKit.selectionUpAction, DefaultEditorKit.selectionDownAction, DefaultEditorKit.selectionEndAction, DefaultEditorKit.selectionEndLineAction, DefaultEditorKit.selectionForwardAction, DefaultEditorKit.selectionNextWordAction, DefaultEditorKit.selectionPreviousWordAction, DefaultEditorKit.selectionBeginWordAction, DefaultEditorKit.selectionEndWordAction, DefaultEditorKit.selectionBeginParagraphAction, DefaultEditorKit.selectionEndParagraphAction, DefaultEditorKit.deleteNextWordAction, DefaultEditorKit.deletePrevWordAction, "toggle-componentOrientation" }; private static final Action ignoreAction= new AbstractAction() { public void actionPerformed(ActionEvent ae) { } }; private static abstract class WrapperAction extends AbstractAction { protected Action wrappedAction; public WrapperAction(Action wrappedAction) { this.wrappedAction= (wrappedAction == null)?ignoreAction:wrappedAction; } }; private class CaretBackwardAction extends WrapperAction { public CaretBackwardAction(Action wrappedAction) { super(wrappedAction); } public void actionPerformed(ActionEvent ae) { if (cur > 0) { cur--; wrappedAction.actionPerformed(ae); System.err.println("cur: "+cur); } } } private class CaretForwardAction extends WrapperAction { public CaretForwardAction(Action wrappedAction) { super(wrappedAction); } public void actionPerformed(ActionEvent ae) { if (cur < line.length()) { cur++; wrappedAction.actionPerformed(ae); System.err.println("cur: "+cur); } } } private class DeleteNextAction extends WrapperAction { public DeleteNextAction(Action wrappedAction) { super(wrappedAction); } public void actionPerformed(ActionEvent ae) { if (cur < line.length()-1) { line.deleteCharAt(cur); wrappedAction.actionPerformed(ae); } } } private class DeletePreviousAction extends WrapperAction { public DeletePreviousAction(Action wrappedAction) { super(wrappedAction); } public void actionPerformed(ActionEvent ae) { if (cur > 0) { line.deleteCharAt(--cur); wrappedAction.actionPerformed(ae); } } } private class InsertTabAction extends WrapperAction { public InsertTabAction(Action wrappedAction) { super(wrappedAction); } public void actionPerformed(ActionEvent ae) { System.err.println("tab"); line.insert(cur++, '\t'); wrappedAction.actionPerformed(ae); } } private class InsertBreakAction extends WrapperAction { public InsertBreakAction(Action wrappedAction) { super(wrappedAction); } public void actionPerformed(ActionEvent ae) { System.err.println("read line: "+line.substring(0, cur)); line.delete(0, cur); cur= 0; wrappedAction.actionPerformed(ae); } } private class DefaultTypedAction extends WrapperAction { public DefaultTypedAction(Action wrappedAction) { super(wrappedAction); } public void actionPerformed(ActionEvent ae) { String content = ae.getActionCommand(); int mod = ae.getModifiers(); if ((content != null) && (content.length() > 0) && ((mod & ActionEvent.ALT_MASK) == (mod & ActionEvent.CTRL_MASK))) { char c = content.charAt(0); System.err.println("char typed content: "+(int)c); if ((c >= 0x20) && (c != 0x7f)) { line.insert(cur++, c); } else if (c == '\n') { System.err.println("read line: "+line.substring(0, cur)); line.delete(0, cur); cur= 0; } else if (c == 0x08) { if (cur > 0) { line.deleteCharAt(--cur); } } else if (c == 0x7f) { System.err.println("delete at: "+cur); if (cur < line.length()-1) { line.deleteCharAt(cur); } } else System.err.println("typed char: "+((int)c)); } wrappedAction.actionPerformed(ae); System.err.println("default typed content: "+line.toString()); } } private class InsertContentAction extends WrapperAction { public InsertContentAction(Action wrappedAction) { super(wrappedAction); } public void actionPerformed(ActionEvent ae) { String content = ae.getActionCommand(); System.err.println("content: "+line.toString()); if (content != null) { line.insert(cur, content); cur+= content.length(); } wrappedAction.actionPerformed(ae); } }; private JTextArea area; private StringBuilder line= new StringBuilder(); private int cur; public TextInputStream(JTextArea area) { this.area= area; initialize(); } private void ignoreActions(ActionMap map, ActionMap par) { for (Object obj : ignores) { if (par.get(obj) != null) map.put(obj, ignoreAction); } } private void changeActions(ActionMap map, ActionMap par) { Action defaultTyped; map.put(DefaultEditorKit.backwardAction, new CaretBackwardAction(par.get(DefaultEditorKit.backwardAction))); map.put(DefaultEditorKit.forwardAction, new CaretForwardAction(par.get(DefaultEditorKit.forwardAction))); map.put(DefaultEditorKit.deleteNextCharAction, new DeleteNextAction(par.get(DefaultEditorKit.deleteNextCharAction))); map.put(DefaultEditorKit.deletePrevCharAction, new DeletePreviousAction(par.get(DefaultEditorKit.deletePrevCharAction))); map.put(DefaultEditorKit.insertTabAction, new InsertTabAction(par.get(DefaultEditorKit.insertTabAction))); map.put(DefaultEditorKit.insertBreakAction, new InsertBreakAction(par.get(DefaultEditorKit.insertBreakAction))); map.put(DefaultEditorKit.insertContentAction, new InsertContentAction(par.get(DefaultEditorKit.insertContentAction))); map.put(DefaultEditorKit.defaultKeyTypedAction, defaultTyped= new DefaultTypedAction(par.get(DefaultEditorKit.defaultKeyTypedAction))); area.getKeymap().setDefaultAction(defaultTyped); } private void initialize() { ActionMap map= new ActionMap(); ActionMap par= area.getActionMap(); area.setEditable(true); area.setEnabled(true); ignoreActions(map, par); changeActions(map, par); map.setParent(par); //for(; par != null; par= par.getParent()) // par.clear(); area.setActionMap(map); } }
b.t.w. thanks for replying again.
kind regards,
JosWhen people rob a bank they get a penalty; when banks rob people they get a bonus.
- 01-25-2011, 07:15 AM #7
- Join Date
- Sep 2008
- Location
- Voorschoten, the Netherlands
- Posts
- 11,408
- Blog Entries
- 7
- Rep Power
- 17
*bump* If anyone tried to run the SCE above (it isn't Short and it obviously isn't Correct ;-) you could notice that the CaretBackwardAction and CaretForwardActions aren't called; also the InsertTab and InsertBreak actions aren't called. The DefaultTypedAction contains code to handle that; why? If I clear out the parent maps (shared by all JTextComponents) no cursor movement is possible anymore. Why?
kind regards,
JosWhen people rob a bank they get a penalty; when banks rob people they get a bonus.
- 01-25-2011, 07:40 AM #8
Totally out of topic, but still...
5000 posts Jos... Great going Buddy, Keep it up. You have been an Idol :D
GoldestJava Is A Funny Language... Really!.gif)
Click on * and add to member reputation, if you find their advices/solutions effective.
- 01-25-2011, 08:05 AM #9
- Join Date
- Sep 2008
- Location
- Voorschoten, the Netherlands
- Posts
- 11,408
- Blog Entries
- 7
- Rep Power
- 17
Thanks; I hope that this thread creates a few more posts because I'm completely stuck with this problem; I spent the better half of the day yesterday on it and I don't get it. All I do is change the entries in the ActionMap of a JTextArea. I suspect them to be called when those particular action events occur, but they don't. The code is a mess now because of all the debugging I did. I hereby solemnly declare that I hate Swing ;-)
kind regards,
JosWhen people rob a bank they get a penalty; when banks rob people they get a bonus.
- 01-25-2011, 08:27 PM #10
Moderator
- Join Date
- Jul 2010
- Location
- California
- Posts
- 1,609
- Rep Power
- 5
I ran the code above. Because you pointed them out I looked specifically at the CaretForward and Backward Actions, which for me are called...if I type in text into a JTextArea, I can forward or back with the arrow keys with the appropriate System.err output and the wrapped Action getting called. At this point I'm not sure what is working and what isn't given the number of actions involved, so if you could itemize them it might help a bit.*bump* If anyone tried to run the SCE above (it isn't Short and it obviously isn't Correct ;-) you could notice that the CaretBackwardAction and CaretForwardActions aren't called; also the InsertTab and InsertBreak actions aren't called. The DefaultTypedAction contains code to handle that; why? If I clear out the parent maps (shared by all JTextComponents) no cursor movement is possible anymore. Why?
- 01-26-2011, 07:10 AM #11
- Join Date
- Sep 2008
- Location
- Voorschoten, the Netherlands
- Posts
- 11,408
- Blog Entries
- 7
- Rep Power
- 17
How strange; did you leave the clearing of the parent maps commented? The symptoms when I run it are: the cursor keys make the cursor move but not through my Actions (no output on stderr). If I clear all the parent maps the cursor keys don't move anymore (which is sort of understandable because there are no Actions assigned in the map(s) anymore) but still my Actions aren't called. I am starting to believe in Voodoo ;-) I´ll dissect my code this afternoon, I don't like unexplainable differences in behaviour (I'm running Java 1.6.20)
Thanks for replying to this nasty little problem again.
kind regards,
Jos
edit: for me only the default typed action work; none of the others are called (I don't see their output of stderr); that's one reason my default typed action is so big, i.e. it handles tabs, enter keys and the deletes while it shouldn't be needed to do it that way.Last edited by JosAH; 01-26-2011 at 07:16 AM.
When people rob a bank they get a penalty; when banks rob people they get a bonus.
- 01-26-2011, 09:58 AM #12
- Join Date
- Sep 2008
- Location
- Voorschoten, the Netherlands
- Posts
- 11,408
- Blog Entries
- 7
- Rep Power
- 17
Found it: I took a shower and made my self a couple of cups of espresso (that old machine is starting to sound like a pneumatic hammer) and sat on the toilet for a couple of minutes (my moment of meditation ;-) After smoking a cigaret it all came to me: it was all my own fault; my JTextAreas are part of my old configuration framework (ahem). It is (almost) non-intrusive so I had forgotten all about it; it reset those KeyMaps and ActionMaps. I disabled it and now it works; there was one other little problem: if I set the default typed action in the KeyMap it works for all JTextComponents, so I changed my code a bit; here it is:
Thanks for participating in this thread.Java Code:package com.dadid.utils.gui; import java.awt.event.ActionEvent; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.ActionMap; import javax.swing.JTextArea; import javax.swing.text.DefaultEditorKit; import javax.swing.text.TextAction; public class TextInputStream { private static final Object[] ignores = { DefaultEditorKit.beginAction, DefaultEditorKit.beginLineAction, DefaultEditorKit.upAction, DefaultEditorKit.downAction, DefaultEditorKit.endAction, DefaultEditorKit.endLineAction, DefaultEditorKit.nextWordAction, DefaultEditorKit.previousWordAction, DefaultEditorKit.pageDownAction, DefaultEditorKit.pageUpAction, DefaultEditorKit.selectAllAction, DefaultEditorKit.selectionBackwardAction, DefaultEditorKit.selectionBeginAction, DefaultEditorKit.selectionBeginLineAction, DefaultEditorKit.selectionUpAction, DefaultEditorKit.selectionDownAction, DefaultEditorKit.selectionEndAction, DefaultEditorKit.selectionEndLineAction, DefaultEditorKit.selectionForwardAction, DefaultEditorKit.selectionNextWordAction, DefaultEditorKit.selectionPreviousWordAction, DefaultEditorKit.selectionBeginWordAction, DefaultEditorKit.selectionEndWordAction, DefaultEditorKit.selectionBeginParagraphAction, DefaultEditorKit.selectionEndParagraphAction, DefaultEditorKit.deleteNextWordAction, DefaultEditorKit.deletePrevWordAction, "toggle-componentOrientation" }; private static final Action ignoreAction= new AbstractAction() { public void actionPerformed(ActionEvent ae) { } }; private abstract class WrapperAction extends TextAction { protected Action wrappedAction; public WrapperAction(Action wrappedAction) { super(""); this.wrappedAction= (wrappedAction == null)?ignoreAction:wrappedAction; } public void actionPerformed(ActionEvent ae) { if (this.getTextComponent(ae) == area) performAction(ae); else if (wrappedAction != null) wrappedAction.actionPerformed(ae); } public abstract void performAction(ActionEvent ae); }; private class IgnoreAction extends WrapperAction { public IgnoreAction(Action wrappedAction) { super(wrappedAction); } public void performAction(ActionEvent ae) { } } private class CaretBackwardAction extends WrapperAction { public CaretBackwardAction(Action wrappedAction) { super(wrappedAction); } public void performAction(ActionEvent ae) { if (cur > 0) { cur--; wrappedAction.actionPerformed(ae); } } } private class CaretForwardAction extends WrapperAction { public CaretForwardAction(Action wrappedAction) { super(wrappedAction); } public void performAction(ActionEvent ae) { if (cur < line.length()) { cur++; wrappedAction.actionPerformed(ae); } } } private class DeleteNextAction extends WrapperAction { public DeleteNextAction(Action wrappedAction) { super(wrappedAction); } public void performAction(ActionEvent ae) { if (cur < line.length()) { line.deleteCharAt(cur); wrappedAction.actionPerformed(ae); } } } private class DeletePreviousAction extends WrapperAction { public DeletePreviousAction(Action wrappedAction) { super(wrappedAction); } public void performAction(ActionEvent ae) { if (cur > 0) { line.deleteCharAt(--cur); wrappedAction.actionPerformed(ae); } } } private class InsertTabAction extends WrapperAction { public InsertTabAction(Action wrappedAction) { super(wrappedAction); } public void performAction(ActionEvent ae) { line.insert(cur++, '\t'); wrappedAction.actionPerformed(ae); } } private class InsertBreakAction extends WrapperAction { public InsertBreakAction(Action wrappedAction) { super(wrappedAction); } public void performAction(ActionEvent ae) { System.err.println("line: "+line.substring(0, cur)); line.delete(0, cur); cur= 0; wrappedAction.actionPerformed(ae); } } private class DefaultTypedAction extends WrapperAction { public DefaultTypedAction(Action wrappedAction) { super(wrappedAction); } public void performAction(ActionEvent ae) { String content = ae.getActionCommand(); int mod = ae.getModifiers(); if ((content != null) && (content.length() > 0) && ((mod & ActionEvent.ALT_MASK) == (mod & ActionEvent.CTRL_MASK))) { char c = content.charAt(0); if ((c >= 0x20) && (c != 0x7f)) { line.insert(cur++, c); } } wrappedAction.actionPerformed(ae); } } private class InsertContentAction extends WrapperAction { public InsertContentAction(Action wrappedAction) { super(wrappedAction); } public void performAction(ActionEvent ae) { String content = ae.getActionCommand(); if (content != null) { line.insert(cur, content); cur+= content.length(); } wrappedAction.actionPerformed(ae); } }; private JTextArea area; private StringBuilder line= new StringBuilder(); private int cur; public TextInputStream(JTextArea area) { this.area= area; initialize(); } private Action get(ActionMap map, Object key) { for (; map != null; map= map.getParent()) { Action a= map.get(key); if (a != null) return a; } return null; } private void ignoreActions(ActionMap map, ActionMap par) { for (Object obj : ignores) { Action ignoreAction= get(par, obj); if (ignoreAction != null) map.put(obj, new IgnoreAction(ignoreAction)); } } private void changeActions(ActionMap map, ActionMap par) { Action defaultTyped; map.put(DefaultEditorKit.backwardAction, new CaretBackwardAction(get(par, DefaultEditorKit.backwardAction))); map.put(DefaultEditorKit.forwardAction, new CaretForwardAction(get(par, DefaultEditorKit.forwardAction))); map.put(DefaultEditorKit.deleteNextCharAction, new DeleteNextAction(get(par, DefaultEditorKit.deleteNextCharAction))); map.put(DefaultEditorKit.deletePrevCharAction, new DeletePreviousAction(get(par, DefaultEditorKit.deletePrevCharAction))); map.put(DefaultEditorKit.insertTabAction, new InsertTabAction(get(par, DefaultEditorKit.insertTabAction))); map.put(DefaultEditorKit.insertBreakAction, new InsertBreakAction(get(par, DefaultEditorKit.insertBreakAction))); map.put(DefaultEditorKit.insertContentAction, new InsertContentAction(get(par, DefaultEditorKit.insertContentAction))); map.put(DefaultEditorKit.defaultKeyTypedAction, defaultTyped= new DefaultTypedAction(get(par, DefaultEditorKit.defaultKeyTypedAction))); area.getKeymap().setDefaultAction(defaultTyped); } private void initialize() { ActionMap map= new ActionMap(); ActionMap par= area.getActionMap(); area.setEditable(true); area.setEnabled(true); ignoreActions(map, par); changeActions(map, par); map.setParent(par); // for(; par != null; par= par.getParent()) // par.clear(); area.setActionMap(map); } }
kind regards,
JosWhen people rob a bank they get a penalty; when banks rob people they get a bonus.
Similar Threads
-
Question concerning question marks and colons
By jim01 in forum New To JavaReplies: 17Last Post: 01-14-2011, 12:05 AM -
Question mark colon operator question
By orchid in forum Advanced JavaReplies: 9Last Post: 12-19-2010, 08:49 AM -
Do while question
By felito in forum New To JavaReplies: 14Last Post: 11-10-2010, 07:46 PM -
MVC question
By Tom_ in forum Advanced JavaReplies: 1Last Post: 08-12-2010, 12:01 PM -
Need help with a question please
By sonal in forum New To JavaReplies: 1Last Post: 11-29-2007, 09:17 PM


LinkBack URL
About LinkBacks
Reply With Quote

Bookmarks