Java Forum / General / January 2006
KeyStroke replacement?
Knute Johnson - 01 Jan 2006 07:01 GMT I need to be able to press an F key (or any of the keys that don't produce a character) and produce a character in a JTextField. I tried to use a KeyListener to detect the F key and then use setKeyCode() and setKeyChar() but that doesn't produce any output. The reason I need this is that my customer doesn't think his client can type the ALT 0??? on the numeric keypad. He doesn't want to lose any of the existing keys so it's the F keys. Any ideas would be greatly appreciated. What I really need is a way to map one KeyStroke to another but I can't find anything in the API docs to do that.
Thanks,
 Signature Knute Johnson email s/nospam/knute/
Andrey Kuznetsov - 01 Jan 2006 09:13 GMT at-first consume original event, then create new KeyEvent with appropriate KeyStroke and dispatch it.
 Signature Andrey Kuznetsov http://uio.imagero.com Unified I/O for Java http://reader.imagero.com Java image reader http://jgui.imagero.com Java GUI components and utilities
Knute Johnson - 01 Jan 2006 21:23 GMT > at-first consume original event, then create new KeyEvent > with appropriate KeyStroke and dispatch it. Thanks for your response. Please see my reply to Michael.
 Signature Knute Johnson email s/nospam/knute/
Andrey Kuznetsov - 02 Jan 2006 00:41 GMT >> at-first consume original event, then create new KeyEvent >> with appropriate KeyStroke and dispatch it. > > Thanks for your response. Please see my reply to Michael. hmm, another way it to create key bindings with
getKeyMap(condition).put(KeyStroke, actionName); getActionMap().put(actionName, action);
if it does not work (however I beleave that it should work) you should override processKeyEvent()
 Signature Andrey Kuznetsov http://uio.imagero.com Unified I/O for Java http://reader.imagero.com Java image reader http://jgui.imagero.com Java GUI components and utilities
Knute Johnson - 02 Jan 2006 04:00 GMT >>>at-first consume original event, then create new KeyEvent >>>with appropriate KeyStroke and dispatch it. [quoted text clipped - 8 lines] > if it does not work (however I beleave that it should work) > you should override processKeyEvent() Andrey:
I did try that and it works well to give you an ActionEvent on the key press. The problem comes next when you have to get the text from the component and stuff the character into it. I had problems getting the cursor in the right place and not having the text slide around in the component. The KeyboardFocusManager and KeyEventDispatcher seemed to work better.
Thanks,
 Signature Knute Johnson email s/nospam/knute/
Andrey Kuznetsov - 02 Jan 2006 08:18 GMT > I did try that and it works well to give you an ActionEvent on the key > press. The problem comes next when you have to get the text from the > component and stuff the character into it. I had problems getting the > cursor in the right place and not having the text slide around in the > component. The KeyboardFocusManager and KeyEventDispatcher seemed to work > better. see Michael's answer ;-) Note that you don't need to know anything about caret position, you can just create new KeyEvent with right KeyStroke and let your component process it.
 Signature Andrey Kuznetsov http://uio.imagero.com Unified I/O for Java http://reader.imagero.com Java image reader http://jgui.imagero.com Java GUI components and utilities
Knute Johnson - 02 Jan 2006 17:51 GMT >>I did try that and it works well to give you an ActionEvent on the key >>press. The problem comes next when you have to get the text from the [quoted text clipped - 7 lines] > you can just create new KeyEvent with right KeyStroke and let your component > process it. Can you give me a short example or a little more detailed explanation?
 Signature Knute Johnson email s/nospam/knute/
Andrey Kuznetsov - 03 Jan 2006 01:28 GMT >> see Michael's answer ;-) >> Note that you don't need to know anything about caret position, >> you can just create new KeyEvent with right KeyStroke and let your >> component process it. > > Can you give me a short example or a little more detailed explanation? import javax.swing.*; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; import java.awt.*;
/** * Inserts '0' if user press F4 */ public class FTextField extends JTextField {
public FTextField() { Action f4 = new AbstractAction() { public void actionPerformed(ActionEvent e) { KeyEvent ek = new KeyEvent(FTextField.this, KeyEvent.KEY_TYPED, e.getWhen(), 0, KeyEvent.VK_UNDEFINED, '0'); dispatchEvent(ek); } }; getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_F4, 0, false), "actionF4"); getActionMap().put("actionF4", f4); }
public static void main(String[] args) { JFrame frame = new JFrame(); frame.getContentPane().add(new FTextField(), BorderLayout.NORTH); frame.pack(); frame.show();
} }
 Signature Andrey Kuznetsov http://uio.imagero.com Unified I/O for Java http://reader.imagero.com Java image reader http://jgui.imagero.com Java GUI components and utilities
Roedy Green - 03 Jan 2006 03:25 GMT On Tue, 3 Jan 2006 02:28:31 +0100, "Andrey Kuznetsov" <spam0@imagero.com.invalid> wrote, quoted or indirectly quoted someone who said :
> * Inserts '0' if user press F4 See http://mindprod.com/products1.html#KEYPLAY
It will show you just what events are generated when you hit various keys. I think that way clear up your problem.
 Signature Canadian Mind Products, Roedy Green. http://mindprod.com Java custom programming, consulting and coaching.
Andrey Kuznetsov - 03 Jan 2006 08:30 GMT >> * Inserts '0' if user press F4 > > See http://mindprod.com/products1.html#KEYPLAY > > It will show you just what events are generated when you hit various > keys. I think that way clear up your problem. which problem?
 Signature Andrey Kuznetsov http://uio.imagero.com Unified I/O for Java http://reader.imagero.com Java image reader http://jgui.imagero.com Java GUI components and utilities
Knute Johnson - 03 Jan 2006 19:45 GMT > On Tue, 3 Jan 2006 02:28:31 +0100, "Andrey Kuznetsov" > <spam0@imagero.com.invalid> wrote, quoted or indirectly quoted someone [quoted text clipped - 6 lines] > It will show you just what events are generated when you hit various > keys. I think that way clear up your problem. Thanks Roedy. That reminds me of a utility I wrote years ago in C to capture key codes. getc() was a lot simpler :-).
 Signature Knute Johnson email s/nospam/knute/
Knute Johnson - 03 Jan 2006 19:35 GMT >>>see Michael's answer ;-) >>>Note that you don't need to know anything about caret position, [quoted text clipped - 34 lines] > } > } Andrey:
Thanks very much Andrey for the sample code. That is much better than what I came up with.
Do you have any idea why Component.dispatchEvent() is final and not public? I would think that would make all of this messing around a lot simpler to override dispatchEvent().
 Signature Knute Johnson email s/nospam/knute/
Andrey Kuznetsov - 04 Jan 2006 00:37 GMT > Thanks very much Andrey for the sample code. That is much better than > what I came up with. you are welcome
> Do you have any idea why Component.dispatchEvent() is final and not > public? I would think that would make all of this messing around a lot > simpler to override dispatchEvent(). hmm, why sun makes so many things so difficult?..
BTW final and protected in not the problem, you can create component which has for example such method
public void dispatchKeyEvent(KeyEvent e) { dispatchEvent(e); }
 Signature Andrey Kuznetsov http://uio.imagero.com Unified I/O for Java http://reader.imagero.com Java image reader http://jgui.imagero.com Java GUI components and utilities
Knute Johnson - 04 Jan 2006 01:57 GMT >>Thanks very much Andrey for the sample code. That is much better than >>what I came up with. [quoted text clipped - 13 lines] > dispatchEvent(e); > } Yes I know, what I had in mind was trapping the event as it came by (through dispatchEvent()) and making changes there. In the KeyboardFocusManager, dispatchKeyEvent() is public. I'm no expert but I would have thought that that would have been much easier than the global KeyboardFocusManager or using the Actions.
 Signature Knute Johnson email s/nospam/knute/
Michael Dunn - 01 Jan 2006 10:13 GMT >I need to be able to press an F key (or any of the keys that don't produce a character) and produce >a character in a JTextField. I tried to use a KeyListener to detect the F key and then use [quoted text clipped - 3 lines] >I really need is a way to map one KeyStroke to another but I can't find anything in the API docs to >do that. if this is a continuation of the ALT 0189 for ½ this might be one way
import java.awt.*; import javax.swing.*; import java.awt.event.*; import javax.swing.text.JTextComponent; class Testing extends JFrame { public Testing() { setLocation(400,300); setDefaultCloseOperation(EXIT_ON_CLOSE); JPanel p = new JPanel(new GridLayout(2,1)); p.add(new JTextField(10)); p.add(new JTextField(10)); getContentPane().add(p,BorderLayout.NORTH); getContentPane().add(new JTextArea(5,10),BorderLayout.CENTER); pack(); KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(new KeyEventDispatcher(){ public boolean dispatchKeyEvent(KeyEvent ke){ if(ke.getID()==KeyEvent.KEY_PRESSED && ke.getKeyCode() == KeyEvent.VK_F1) { if(KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() instanceof JTextComponent) { JTextComponent tc = (JTextComponent)KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); tc.setText(tc.getText()+"\u00BD"); } } return false;}}); } public static void main(String[] args){new Testing().setVisible(true);} }
Knute Johnson - 01 Jan 2006 21:23 GMT > if this is a continuation of the ALT 0189 for ½ > this might be one way [quoted text clipped - 32 lines] > public static void main(String[] args){new Testing().setVisible(true);} > } Michael:
Thanks for your code sample. I liked your approach but I need to be able to only have one component with the capability. I started with your code and below is what I came up with. It works and it works with the special document that I have to have in addition. Any suggestions for improvement or simplification would be greatly appreceiated.
There are a couple of issues with this approach. It does not correctly handle KEY_PRESSED events that also generate KEY_TYPED events (two characters will be output). I don't really understand how to consume the KeyEvent, just putting in keyEvent.consume() doesn't do it. If I consume the KeyEvent and return true from dispatchKeyEvent() it eats up all characters except the F keys (I really don't know what is going on there). I am concerned that I don't understand the whole KeyboardFocusManager thing enough to know for sure that I will always have the correct current KeyboardFocusManager and that my events will then get processed.
import java.awt.*; import java.awt.event.*; import java.util.*; import javax.swing.*; import javax.swing.text.*;
public class MyKeyEventDispatcher implements KeyEventDispatcher { public HashSet<Component> comps = new HashSet<Component>(); public HashMap<Integer,Character> swaps = new HashMap<Integer,Character>();
public boolean dispatchKeyEvent(KeyEvent keyEvent) { Component comp = keyEvent.getComponent(); if (comps.contains(comp) && keyEvent.getID() == KeyEvent.KEY_PRESSED) { Set<Integer> swapSet = swaps.keySet(); Iterator<Integer> it = swapSet.iterator(); while (it.hasNext()) { Integer keyCode = it.next(); if (keyCode.intValue() == keyEvent.getKeyCode()) { KeyEvent ev = new KeyEvent(comp,KeyEvent.KEY_TYPED, System.currentTimeMillis(),0,KeyEvent.VK_UNDEFINED, swaps.get(keyCode).charValue()); KeyboardFocusManager.getCurrentKeyboardFocusManager(). redispatchEvent(comp,ev); } } } return false; }
public static void main(String[] args) { Runnable r = new Runnable() { public void run() { JFrame f = new JFrame(); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JTextField tf = new JTextField(); f.add(tf,BorderLayout.NORTH); JTextField tf2 = new JTextField(); f.add(tf2,BorderLayout.SOUTH);
MyKeyEventDispatcher med = new MyKeyEventDispatcher(); med.swaps.put( new Integer(KeyEvent.VK_F4),new Character('\u00bd')); med.comps.add(tf);
KeyboardFocusManager kbfm = KeyboardFocusManager.getCurrentKeyboardFocusManager(); kbfm.addKeyEventDispatcher(med);
f.pack(); f.setVisible(true); } }; EventQueue.invokeLater(r); } }
 Signature Knute Johnson email s/nospam/knute/
Michael Dunn - 02 Jan 2006 06:34 GMT >> if this is a continuation of the ALT 0189 for ½ >> this might be one way [quoted text clipped - 103 lines] > } > } if this is for only a single component (and I think I can see what you're trying to do) perhaps an Action might be the easier way to go
here's a simple action demo, F4 inserts ½ in tf (at the caret position and when tf has the focus)
import java.awt.*; import java.awt.event.*; import javax.swing.*;
class Testing extends JFrame { public Testing() { setLocation(400,100); setDefaultCloseOperation(EXIT_ON_CLOSE); JPanel jp = new JPanel(new GridLayout(2,1)); final JTextField tf = new JTextField(10); final JTextField tf2 = new JTextField(10); jp.add(tf); jp.add(tf2); getContentPane().add(jp); pack(); Action actionF4 = new AbstractAction() { public void actionPerformed(ActionEvent e) { int pos = tf.getCaretPosition(); tf.setText(""+new StringBuffer(tf.getText()).insert(pos,"\u00bd")); tf.setCaretPosition(pos+1);}}; tf.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke("F4"), "actionF4"); tf.getActionMap().put("actionF4", actionF4); } public static void main (String[] args){new Testing().setVisible(true);} }
Knute Johnson - 02 Jan 2006 17:50 GMT >>>if this is a continuation of the ALT 0189 for ½ >>>this might be one way [quoted text clipped - 136 lines] > public static void main (String[] args){new Testing().setVisible(true);} > } Michael:
Thanks, I did try that and it has a problem with my special document that limits the length of text that can be input into the field and it has a problem when with text alignment if the field is smaller than the text string (the text jumps around in the field window).
I am surprised that there is not a simple component level way to do this but you got me started onto what I needed.
Thanks,
 Signature Knute Johnson email s/nospam/knute/
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|