Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / January 2006

Tip: Looking for answers? Try searching our database.

KeyStroke replacement?

Thread view: 
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 Magazines

Get 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 ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.