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 / GUI / June 2004

Tip: Looking for answers? Try searching our database.

keyboard handling

Thread view: 
user@domain.invalid - 27 Jun 2004 23:52 GMT
Hi,

I want to change the output to a JTtextbox based on user input.
For example:
user types in Ctrl + Alt + Shoft + B, i want to detect this and send to
the textbox a N or user types in Ctrl + Alt + D, i want to detect this
and send to the textbox a A for example.

Pleas who can help me.

Thanks,

Anand
VisionSet - 28 Jun 2004 00:44 GMT
> Hi,
>
[quoted text clipped - 5 lines]
>
> Pleas who can help me.

I assume you mean JTextField.

Something like the following, look up java.awt.event.KeyEvent
Not compiled it, but its close.

final JTextField myTextField = new JTextField();

myTextField.addKeyListener(new KeyAdapter() {
   public void keyTyped(KeyEvent e) {
       if(e.isAltDown() && e.isControlDown()) {
           char chr = e.getKeyChar() {
           switch(chr) {
               case 'b': myTextField.setText("N"); break;
               case 'd': myTextField.setText("A"); break;
           }
       }

   }
});

--
Mike W
user@domain.invalid - 28 Jun 2004 10:21 GMT
Hi Mike W,

Thanks for you reply.
I tried you coding, but i don't get the result i want.
The problem is that when actionkeys are used, no keytype event are
generated. Only keyPressed and keyReleased events.

This is what happens when i press Ctl + Alt + k (output from
KeyEventDemo.java)

KEY PRESSED:
    key character = '?'
    key code = 18 (Alt)
    modifiers = 8 (Alt)
KEY PRESSED:
    key character = '?'
    key code = 17 (Ctrl)
    modifiers = 10 (Ctrl+Alt)
KEY PRESSED:
    key character = (an unprintable control character)
    key code = 75 (K)
    modifiers = 10 (Ctrl+Alt)

So it tried this:

  public void processKeyEvent (KeyEvent e)
  {
    if ( (e.getID () == KeyEvent.KEY_TYPED) &&
        Character.isLowerCase (e.getKeyChar ()))
    {
      System.out.println ("keycode=" + e.getKeyCode() );

    // test purpose: change lowercase to uppercase
      e.setKeyChar (Character.toUpperCase (e.getKeyChar ()));
    }
    else
    {
      if ( (e.getID () == KeyEvent.KEY_PRESSED))   
      {
        if (e.isAltDown() && e.isControlDown() && e.isShiftDown())
        {
          char kar=65;
          e.setKeyChar (kar);  //does not work
        }

        if (e.isShiftDown())
        {
          char kar=67;            // does not work either

          KeyEvent nke = new KeyEvent(
              e.getComponent() ,
              e.getID(),
              e.getWhen(),
              e.getModifiers()
              ,67
              ,kar
              ,e.getKeyLocation());

          // consume old event
          e.consume ();
          super.processKeyEvent(nke);
        }
      }
      else
      {
        super.processKeyEvent (e);
      }
    }
  }

I consumed the old keyEvent and tried to generate a new one.
But that one failes and i don't know why?

Bye,

Anand M

source of KeyEventDemo.java
===========================

import javax.swing.*;
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;

public class KeyEventDemo
    extends JFrame
    implements KeyListener, ActionListener
{
  static final String newline = "\n";
  FlowLayout flowLayout1 = new FlowLayout();
  JPanel jPanel1 = new JPanel();
  BorderLayout borderLayout1 = new BorderLayout();
  JButton button = new JButton("Clear");
  JTextArea displayArea = new JTextArea();
  JTextField typingArea = new JTextField();

  //********************************************************************
  public KeyEventDemo ()
  //********************************************************************
  {
    try
    {
      jbInit();
    }
    catch(Exception e)
    {
      e.printStackTrace();
    }
  }

  /** Handle the key typed event from the text field. */
  //********************************************************************
  public void keyTyped (KeyEvent e)
  //********************************************************************
  {
    displayInfo (e, "KEY TYPED: ");
  }

  /** Handle the key pressed event from the text field. */
  //********************************************************************
  public void keyPressed (KeyEvent e)
  //********************************************************************
  {
    displayInfo (e, "KEY PRESSED: ");
  }

  /** Handle the key released event from the text field. */
  //********************************************************************
  public void keyReleased (KeyEvent e)
  //********************************************************************
  {
        displayInfo(e, "KEY RELEASED: ");
  }

  /** Handle the button click. */
  //********************************************************************
  public void actionPerformed (ActionEvent e)
  //********************************************************************
  {
    //Clear the text components.
    displayArea.setText ("");
    typingArea.setText ("");

    //Return the focus to the typing area.
    typingArea.requestFocus ();
    jPanel1.repaint();
  }

  /*
   * We have to jump through some hoops to avoid
   * trying to print non-printing characters
   * such as Shift.  (Not only do they not print,
   * but if you put them in a String, the characters
   * afterward won't show up in the text area.)
   */
  //********************************************************************
  protected void displayInfo (KeyEvent e, String s)
  //********************************************************************
  {
    String charString, keyCodeString, modString, tmpString;

    char c = e.getKeyChar ();
    int keyCode = e.getKeyCode ();
    int modifiers = e.getModifiers ();

    if (Character.isISOControl (c))
    {
      charString = "key character = "
                   + "(an unprintable control character)";
    }
    else
    {
      charString = "key character = '"
                   + c + "'";
    }

    keyCodeString = "key code = " + keyCode
                    + " ("
                    + KeyEvent.getKeyText (keyCode)
                    + ")";

    modString = "modifiers = " + modifiers;
    tmpString = KeyEvent.getKeyModifiersText (modifiers);
    if (tmpString.length () > 0)
    {
      modString += " (" + tmpString + ")";
    }
    else
    {
      modString += " (no modifiers)";
    }

    displayArea.append (s + newline
                        + "    " + charString + newline
                        + "    " + keyCodeString + newline
                        + "    " + modString + newline);

  }

  //********************************************************************
  public static void main (String[] args)
  //********************************************************************
  {
    testFrame testFrame = new testFrame ();
  }
  //********************************************************************
  private void jbInit() throws Exception
  //********************************************************************
  {
    this.setSize(800,600);

    this.getContentPane().setLayout(flowLayout1);
    jPanel1.setLayout(borderLayout1);
    displayArea.setOpaque(true);
    displayArea.setPreferredSize(new Dimension(500, 400));
    displayArea.setText("");
    displayArea.setEditable(false);
    typingArea.setPreferredSize(new Dimension(500, 21));

    typingArea.setText("");
    typingArea.addKeyListener(this);

    this.getContentPane().add(jPanel1, null);
    jPanel1.add(button, BorderLayout.SOUTH);
    jPanel1.add(displayArea, BorderLayout.CENTER);
    jPanel1.add(typingArea, BorderLayout.NORTH);
    this.setVisible(true);

    JPanel contentPane = new JPanel();
    setContentPane(jPanel1);
  }
}

>>Hi,
>>
[quoted text clipped - 28 lines]
> --
> Mike W
VisionSet - 28 Jun 2004 11:04 GMT
> Hi Mike W,
>
> Thanks for you reply.
> I tried you coding, but i don't get the result i want.
> The problem is that when actionkeys are used, no keytype event are
> generated. Only keyPressed and keyReleased events.

Try this listener method instead:

public void keyPressed(KeyEvent e) {
         if(e.isAltDown() && e.isControlDown()) {
             int code = e.getKeyCode();
             switch(code) {
                 case KeyEvent.VK_B: locCombo.setText("N"); break;
                 case KeyEvent.VK_D: locCombo.setText("A"); break;
             }
         }

     }

Signature

Mike W

user@domain.invalid - 28 Jun 2004 11:40 GMT
Hi Mike W,

Thanks for your quick reply.
I have to give you more information.
I'm writing a keyboard definition for a wordprocessor in a foreing
language and using a specific font.
Each key on the keyboard can represent for 4 characters.
For example:
a unshifted generates an a (for example)
a shifted i generate a z (for example)
a + ctrl + alt generates a d (for example)
a  + ctrl + alt + shift generates a k (for example)
So i can't use setText. That is my main problem. Otherwise i delete the
previous typed characters and i don't know where the cursor is in the
textfield.

In some way i have to send the right character replacing the character
typed in bye the user.

For normal characters (no action key) no problem. But in combination
with action keys (shift, ctrl, alt) i don't know how to handle it.
I hope you have more information over what i try to do.

Thanks so far.

Anand

>>Hi Mike W,
>>
[quoted text clipped - 15 lines]
>
>       }
ak - 28 Jun 2004 12:13 GMT
> Each key on the keyboard can represent for 4 characters.
> For example:
[quoted text clipped - 12 lines]
> with action keys (shift, ctrl, alt) i don't know how to handle it.
> I hope you have more information over what i try to do.

instead of setText() you should use getDocument().insertString();

Signature

http://uio.dev.java.net Unified I/O for Java
http://reader.imagero.com Java image reader

user@domain.invalid - 28 Jun 2004 16:04 GMT
Hi ak,

I tried your solution but i get errors. (cannot resolve symbol: method
getDocument())

is getDocument().insertString() java of JavaScript?
I use Java. If it is Java, which library?

This is the coding i use:

  public void processKeyEvent (KeyEvent e)
  {
    System.out.println (e.getModifiersEx ());

    if ( (e.getID () == KeyEvent.KEY_TYPED) &&
        Character.isLowerCase (e.getKeyChar ()))
    {
      System.out.println ("keycode=" + e.getKeyCode ());
      e.setKeyChar (Character.toUpperCase (e.getKeyChar ()));
    }
    else
    {
      if ( (e.getID () == KeyEvent.KEY_PRESSED))
      {
        //control of alt en ctrl zijn ingedrukt. Shift is uit.
        if (e.isControlDown () && e.isAltDown ())
        {
          int code = e.getKeyCode ();
          switch (code)
          {
            case KeyEvent.VK_B:
              getDocument ().insertString ();
            case KeyEvent.VK_D:
              locCombo.setText ("A");
              break;
          }

          if (e.isShiftDown ())
          {
            System.out.println ("shift + " + e.getKeyCode ());
            char kar = 67;

            KeyEvent nke = new KeyEvent (
                e.getComponent (),
                e.getID (),
                e.getWhen (),
                e.getModifiers ()
                , 67
                , kar
                , e.getKeyLocation ());

            // consume old event
            e.consume ();
            super.processKeyEvent (nke);
          }
        }
      }
      else
      {
        super.processKeyEvent (e);
      }
    }
  }
>>Each key on the keyboard can represent for 4 characters.
>>For example:
[quoted text clipped - 14 lines]
>
> instead of setText() you should use getDocument().insertString();
VisionSet - 28 Jun 2004 17:58 GMT
> Hi ak,
>
[quoted text clipped - 16 lines]
>                locCombo.setText ("A");
>                break;

getDocument() is a javax.swing.text.JTextComponent method which all
sublclasses such as JTextField inherit.

so:

Document myDoc = myTextField.getDocument();
myDoc.insertString(int offset, String string, null);

you will need to get the length of the document to determine where to
insert.
And you NEED to get more used to API based research on your own.

--
Mike W
user@domain.invalid - 28 Jun 2004 23:56 GMT
Hi Mike,

Youre right, i need to do more research. But after 3 week of searching i
gave up and tried this way. I'm a newbie at Java programming.
I have build another application with the same functionality in Visual
Basic without any problem.
But due to some bugs in windows Richteditcontrol i want to make this
application in Java because i don't have Richteditcontrol and other ocx
problems with java.

No regarding to this problem.
The solution you are describing makes it necessary for me to have a
complete administration about cursor positioing.

In Visual Basic, for example, it is very easy to change the keycode
whether a keytyped, or a keypressed event occurs. In VB i change the
keycode and the right character is send to the textfield. Very simple
and no administration is needed about cursor position.
This also can be done in Java but only when a key_typed event occurs. If
i'm right. Not when a keyPressed event occurs.

For a keytyped event is works. For example:

 if ( (e.getID () == KeyEvent.KEY_TYPED) &&
        Character.isLowerCase (e.getKeyChar ()))
    {
      e.setKeyChar (Character.toUpperCase (e.getKeyChar ()));
    }

If i'm right then when a key is pressed and it is a action key, no
key_typed event occurs. Is there a way to do that in a simple way.
It seems to me that that is a better solution that the one you describe.
I tried that also, but i get stuck. Because i don't have enough
knowledge about Java and generating KeyEvents.

My main problem is how to replace that specific character (Ctrl + Shift
+ alt + <a key>) by a normal key so that a key_typed event occurs.
I don't want to do any administration about cursor position etc.
In may opinion it must be possible to do the same trick as with
Key_TYPED event or generate a Key_Typed event somehow. But i don't know how.

I tried this:

  public void keyPressed (KeyEvent e)
  {
    System.out.println("id = " + e.getID());
    char cha=67;
    KeyEvent nke = new KeyEvent (
        e.getComponent (),
        e.getID (),
        e.getWhen (),
        e.getModifiers ()
        , 67
        , cha
        , e.getKeyLocation ());

    // consume old event
    e.consume ();
    super.processKeyEvent (nke);

I tried here to create a new keyevent with a normal character. This one
must replace for ewample Ctrl+Alt+D into a normal B

But i doesn't work. Nothing happens and i canno't find out way :-(
If you can help me solving this problem, than my problem is solved.

>>Hi ak,
>>
[quoted text clipped - 31 lines]
> --
> Mike W
Jim Sculley - 29 Jun 2004 03:05 GMT
> Hi Mike,
>
[quoted text clipped - 16 lines]
> This also can be done in Java but only when a key_typed event occurs. If
> i'm right. Not when a keyPressed event occurs.

You are approaching this problem from much too low a level.  Swing
provides the InputMap and ActionMap classes to make this fairly
straightforward.  Here's a small example that substitutes 'a' when
CTRL-ALT-E is pressed, and substitutes 'b' when CTRl_ALT-N is pressed.
Holding down CTRL-ALT and then pressing E followed by N results in 'ab'
being displayed in the JTextField.

========================
public class SubstituteKey {
    private static JTextField tf;
    public static void main(String[] args) {
        tf = new JTextField();
        //Modify the InputMap and ActionMap
        KeyStroke ctrlAltE = KeyStroke.getKeyStroke(
                KeyEvent.VK_E,
                InputEvent.CTRL_MASK | InputEvent.ALT_MASK,
                false);
        KeyStroke ctrlAltN = KeyStroke.getKeyStroke(
                KeyEvent.VK_N,
                InputEvent.CTRL_MASK | InputEvent.ALT_MASK,
                false);
        SubstituteCharAction insertA = new SubstituteCharAction('a');
        SubstituteCharAction insertB = new SubstituteCharAction('b');
        tf.getInputMap().put(ctrlAltE, "insertA");
        tf.getInputMap().put(ctrlAltN, "insertB");
        tf.getActionMap().put("insertA", insertA);
        tf.getActionMap().put("insertB", insertB);
        //Display sample window
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.getContentPane().add(tf, BorderLayout.SOUTH);
        f.setSize(400,300);
        f.setVisible(true);
    }

    //Helper Action class that inserts the correct text
    private static class SubstituteCharAction extends AbstractAction {

        private String subChar;

        private SubstituteCharAction(char c) {
           this.subChar = String.valueOf(c);
        }
       
        public void  actionPerformed(ActionEvent ae) {
           try {
               tf.getDocument().insertString(
                        tf.getCaretPosition(), subChar, null);
           } catch (BadLocationException ble) {
               ble.printStackTrace();
           }
        }
    }
}
=========================

Jim S.

Signature

Remove my extraneous mandibular appendages to reply via email.

user@domain.invalid - 29 Jun 2004 12:44 GMT
Hi Jim,

Thank you for your reply.
I have seen your solution. It is not a bad solution! What about
performance? If i'm right, than i have to define for
47 keys (1-0, a-z, -+[]\`,./;')  * 4 times (Unshift, Shift, CtrlAlt,
Shift,CtrlAlt) a keystroke = 169 keystrokes. Is this correct or do i
misunderstand your solution?

Anand

>> Hi Mike,
>>
[quoted text clipped - 74 lines]
>
> Jim S.
Jim Sculley - 29 Jun 2004 13:31 GMT
> Hi Jim,
>
> Thank you for your reply.
> I have seen your solution. It is not a bad solution! What about
> performance?

The best way to evaluate performance is to try it.  The standard
JTextField has an InputMap with 33 entries and an ActionMap with 59 entries.

> If i'm right, than i have to define for
> 47 keys (1-0, a-z, -+[]\`,./;')  * 4 times (Unshift, Shift, CtrlAlt,
> Shift,CtrlAlt) a keystroke = 169 keystrokes. Is this correct or do i
> misunderstand your solution?

You only have to add entries to the InputMap and ActionMap for key
strokes that differ from the default.  So, if you want an unshifted 'a'
to still be an 'a' in the JTextField, you do not need entries in the
maps for it.

Jim S.
Signature

Remove my extraneous mandibular appendages to reply via email.

user@domain.invalid - 29 Jun 2004 20:35 GMT
Hi Jim,

Two questions:
> The best way to evaluate performance is to try it.  The standard
> JTextField has an InputMap with 33 entries and an ActionMap with 59
> entries.
1. How can i change the maximum entries. I have more than 33 and 59.
Is that with:
setMaximumSize(Dimension maximumSize)          
Sets the maximum size of this component to a constant value

2. I'm trying your solution. I try to redefine the a-button for 4 options.
a -> k as result
Shift + a -> l as result
CtrlAlt + a -> m as result
ShiftCtrlAlt + a -> n as result.

I have a problem with Shift + a. I get as result lA (two characters).
As far as i can see, is my coding correct. Can you please take a look at
it. The other options gives the results i want (one character).
Here is the code:

import javax.swing.*;
import java.awt.event.*;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.*;
import javax.swing.text.*;

public class SubstituteKey
{
  private static JTextField tf;
  public static void main(String[] args)
  {
    tf = new JTextField();

    //Modify the InputMap and ActionMap
    KeyStroke k_a = KeyStroke.getKeyStroke('a');
    SubstituteCharAction insert_k_a = new SubstituteCharAction('k');
    tf.getInputMap().put(k_a, "insert_k_a");
    tf.getActionMap().put("insert_k_a", insert_k_a);

    KeyStroke k_Sa = KeyStroke.getKeyStroke(KeyEvent.VK_A
    , InputEvent.SHIFT_DOWN_MASK, false);
    SubstituteCharAction insert_k_Sa = new SubstituteCharAction('l');
    tf.getInputMap().put(k_Sa, "insert_k_Sa");
    tf.getActionMap().put("insert_k_Sa", insert_k_Sa);

    KeyStroke k_CAa = KeyStroke.getKeyStroke(KeyEvent.VK_A
      , InputEvent.CTRL_DOWN_MASK | InputEvent.ALT_DOWN_MASK, false);
    SubstituteCharAction insert_k_CAa = new SubstituteCharAction('m');
    tf.getInputMap().put(k_CAa, "insert_k_CAa");
    tf.getActionMap().put("insert_k_CAa", insert_k_CAa);

    KeyStroke k_SCAa = KeyStroke.getKeyStroke(KeyEvent.VK_A
    , InputEvent.SHIFT_DOWN_MASK | InputEvent.CTRL_DOWN_MASK |        
InputEvent.ALT_DOWN_MASK, false);
    SubstituteCharAction insert_k_SCAa = new SubstituteCharAction('n');
    tf.getInputMap().put(k_SCAa, "insert_k_SCAa");
    tf.getActionMap().put("insert_k_SCAa", insert_k_SCAa);

    //Display sample window
    JFrame f = new JFrame();
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.getContentPane().add(tf, BorderLayout.SOUTH);
    f.setSize(400, 300);
    f.setVisible(true);
  }

  //Helper Action class that inserts the correct text
  private static class SubstituteCharAction
      extends AbstractAction
  {

    private String subChar;

    private SubstituteCharAction(char c)
    {
      this.subChar = String.valueOf(c);
    }

    public void actionPerformed(ActionEvent ae)
    {
      try
      {
        tf.getDocument().insertString(
            tf.getCaretPosition(), subChar, null);
      }
      catch (BadLocationException ble)
      {
        ble.printStackTrace();
      }
    }
  }
}

Bye,

Anand
Jim Sculley - 30 Jun 2004 02:20 GMT
> Hi Jim,
>
[quoted text clipped - 6 lines]
> setMaximumSize(Dimension maximumSize)          Sets the maximum size of
> this component to a constant value

There is no 'maximum'.  I provided the values 33 and 59 simply as a
refrence to show that the 150 you require isn't excessive.

> 2. I'm trying your solution. I try to redefine the a-button for 4 options.
> a -> k as result
[quoted text clipped - 5 lines]
> As far as i can see, is my coding correct. Can you please take a look at
> it. The other options gives the results i want (one character).

In looking at this, I stumbled across a class I didn't know about:
Keymap.  It makes things a little easier by hiding the InputMap and
ActionMap stuff:

Keymap kMap = someTextField.getKeymap();
kMap.addActionForKeyStroke(shiftA, insertL);
kMap.addActionForKeyStroke(ctrlAltA, insertM);
kMap.addActionForKeyStroke(ctrlAltShiftA, insertN);

where 'shiftA' is a KeyStroke and 'insertL' is a SubstituteCharAction,
just as before.

The Keymap also helps solve the Shift problem.  Keymap has a method
called setDefaultAction(Action a).  this method is used to set the
default action that should take place when a key binding is not located
in the Keymap.  If you set the default action to be an action that does
nothing, Shift + a will work as expected.  However, typing 'a' by
itself, will result in no text being added to the JTextField.  you can
get around this by creating mapping for these unmodified keys as well.

One side effect of all this remapping of keys is that the behavior when
typing while text is selected may not be what you expect.  To truly get
all the behavcior you want, you may have to look at providing your own
EditorKit implementation to handle all the details.

Jim S.

Signature

Remove my extraneous mandibular appendages to reply via email.

user@domain.invalid - 30 Jun 2004 09:52 GMT
Hi Jim,

I tried another solution. That one that had been suggested by ak and
Visionset.
With your coding about getDocument and getCaretPosition and their
information i have what i wanted now. It is low-level but with maximum
control for me.
Thanks for your help guys.

Bye,

Anand.


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.