[Last Call] Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

How to control keyboard focus?

Posted on 2005-04-29
11
Medium Priority
?
400 Views
Last Modified: 2012-08-13
Hi Experts,

The following code is not working the way I want.
These are the requirements:
1. the top area (JTextPane, light gray in color) is user typing area.
   It has the keyboard focus all the time. It only should receive letters, not any numbers.

2. the bottom area (JTextArea, gray in color) is for ONLY display numbers recevied either
   from keypad (0-9 and  + -) or from the top of keyboard (0-9). It NEVER has focus on it.
   So user should never be able to type on this area.

Here is an example:
I type in the top area the text as this: This is my phone number : 123-456-7890.
"This is my phone number :" should be shown on the top area.
"123-456-7890" should NOT be shown on top area, it should be diplayed on bottom area.


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

public class TestKeypad extends JFrame implements KeyListener
{
      final static int WIDTH = 600;
      final static int HEIGTH = 500;

      //Text pane for user to type, it has the focus all the time
      private JTextPane typingArea=null;

      //Text field display numbers, it never has focus
      private JTextArea displayArea = null;

      // The current keyboard focus manager
      private KeyboardFocusManager kfm = null;

      private DefaultStyledDocument doc = null;


      public TestKeypad(){
            super();
            initComponents();
      }

      private void initComponents(){

        setTitle("Test input from Keypad");
        setSize(WIDTH, HEIGTH);

        JPanel content = (JPanel) getContentPane();
        content.setLayout( new GridLayout(2, 1, 5,5));

        doc = new DefaultStyledDocument();
            typingArea = new JTextPane(doc);
            typingArea.setBackground(Color.lightGray);

            displayArea = new JTextArea();
            displayArea.setBackground(Color.gray);


        content.add(typingArea);
        content.add(displayArea);

      }

      public static void main (String arg[])
      {
            TestKeypad frame = new TestKeypad();
            frame.setVisible(true);
      }


    // Key Listener implementation

    //I need user typing area have focus all the time
      public void keyPressed( KeyEvent event )
      {
         typingArea.requestFocus();
         return;
       }


       //I need forward the event to the user typing area.
       public void keyTyped( KeyEvent event )
       {
         kfm.redispatchEvent(typingArea, event );
         return;
       }


       public void keyReleased( KeyEvent event )
       {
              return;
       }

}
0
Comment
Question by:SarahDeng
  • 5
  • 4
  • 2
11 Comments
 
LVL 92

Assisted Solution

by:objects
objects earned 200 total points
ID: 13898829

don't think you need a keylistener, just disable the bottom text area.
and use a custom Document to control what is displayed in top area, and what goes to bottom
0
 
LVL 10

Expert Comment

by:edwardiii
ID: 13898878
Hi, SarahDeng.

I've made some minor edits to your code:

In your initComponents():

          displayArea = new JTextArea(doc);
          //displayArea.setBackground(Color.gray);    --applying the disable method below requires a color change.
          displayArea.disable();

In your public void keyPressed( KeyEvent event ):
              //typingArea.requestFocus();                  --along wit h the above edit, there's no need to requestFocus.
              return;

What we get now is a mirroring of keyboard entries between displayArea and typingArea.  What's required next is
a routine that will take keyboard inputs and (to start with) display non-numeric characters in typingArea and numerics in
displayArea.  What to do with the other characters (+, -, *, etc.) is unclear to me--do you wish them displayed in both
jTextAreas or only in the lower displayArea?
       
0
 

Author Comment

by:SarahDeng
ID: 13899539
Hi objects,

   Could you detail your idea? What kind of custom Document  do you mean? Thanks.


0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:SarahDeng
ID: 13899587
Hi edwardiii,

  I tried your code. I see the mirroring effect. I didn't give much detail of the requirement. In fact, 99% times, user types non-numeric on the typingArea and types a lot. If it is an efficient to mirror keyboard entries in this case?
 Other characters like (+, -, *) from keypad will be shown "displayArea" too, not shown on "typingArea".
0
 
LVL 92

Expert Comment

by:objects
ID: 13899635
> What kind of custom Document  do you mean?

http://java.sun.com/j2se/1.4.2/docs/api/javax/swing/text/Document.html
0
 
LVL 10

Expert Comment

by:edwardiii
ID: 13901888
Hello.

Well, I tried going with object's suggestion of a custom Document, and I based it on the accepted solution found at:
http://www.experts-exchange.com/Programming/Programming_Languages/Java/Q_21313521.html?query=remove+last+character+of+string&topics=86

The code below represents your original code modified to include a "MyDocument" class.  Valid characters are assigned when the component is set
up:

     typingArea = new JTextPane();
     typingArea.setBackground(Color.lightGray);
     typingArea.setDocument(new MyDocument("abcdefghijklmnopqrstuvwxyz"));  

and
     
      displayArea = new JTextArea();
      //displayArea.setBackground(Color.gray);
      displayArea.disable();          
      displayArea.setDocument(new MyDocument("0123456789+-"));

Frustratingly, the displayArea will not take any Alphas, but neither will it take numerals from the top of keyboard (only the number pad at right).  Also
the typingArea will take numerals--one only if from above the keyboard, and endless amounts if from number pad.  Here is the code with the custom Document:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.text.PlainDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import java.text.ParseException;


public class TestKeypad extends JFrame implements KeyListener
{
     final static int WIDTH = 600;
     final static int HEIGTH = 500;

     //Text pane for user to type, it has the focus all the time
     private JTextPane typingArea=null;

     //Text field display numbers, it never has focus
     private JTextArea displayArea = null;

     // The current keyboard focus manager
     private KeyboardFocusManager kfm = null;

     //private DefaultStyledDocument doc = null;
     


     public TestKeypad(){
          super();
          initComponents();
     }

     private void initComponents(){

        setTitle("Test input from Keypad");
        setSize(WIDTH, HEIGTH);

        JPanel content = (JPanel) getContentPane();
        content.setLayout( new GridLayout(2, 1, 5,5));

        //doc = new DefaultStyledDocument();
          typingArea = new JTextPane();
          typingArea.setBackground(Color.lightGray);
          typingArea.setDocument(new MyDocument("abcdefghijklmnopqrstuvwxyz"));        

          displayArea = new JTextArea();
          //displayArea.setBackground(Color.gray);
          displayArea.disable();          
          displayArea.setDocument(new MyDocument("0123456789+-"));

        content.add(typingArea);
        content.add(displayArea);

     }

     public static void main (String arg[])
     {
          TestKeypad frame = new TestKeypad();
          frame.setVisible(true);
     }


    // Key Listener implementation

    //I need user typing area have focus all the time
     public void keyPressed( KeyEvent event )
     {
        typingArea.requestFocus();
        return;
      }


      //I need forward the event to the user typing area.
      public void keyTyped( KeyEvent event )
      {
        kfm.redispatchEvent(typingArea, event );
        return;
      }


      public void keyReleased( KeyEvent event )
      {
             return;
      }

class MyDocument extends PlainDocument {
   
    //private int maxAllowedChars = 0;
    private String validChars = "";
   
    public MyDocument(String valids) {
        super();
        //maxAllowedChars = maxAllowed;
        validChars = valids;
    }
   
    public void insertString(int index, String s, AttributeSet a)
                                        throws BadLocationException {
         if (s == null || s.length() == 0)
             return;
         StringBuffer t = new StringBuffer(getLength() + s.length());
         t.append(getText(0, index));
         t.append(s);
         t.append(getText(index, getLength() - index));

         //String validChars = "0123456789+-"; // <<<<<< Only digits allowed
         for (int i = 0; i < t.length() ; i++)
            if (validChars.indexOf(t.charAt(i)) == - 1)
                return; // don't allow other characters
         //if (t.length()>maxAllowedChars) return; // don't allow more than x chars
       
         super.insertString(index, s, a);
    }
}
 
     
}

I'm also going to include another modified verison of your original class in which I tried to control everything from the keyPressed method.  In it, although I can control the lower displayArea just fine, it seems impossible to auto-remove numerics from the top typingArea:


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

public class TestKeypad extends JFrame implements KeyListener
{
     final static int WIDTH = 600;
     final static int HEIGTH = 500;    
     private String totalString ="";
     //Text pane for user to type, it has the focus all the time
     private JTextPane typingArea;

     //Text field display numbers, it never has focus
     private JTextArea displayArea;

     // The current keyboard focus manager
     //private KeyboardFocusManager kfm = null;

     //private DefaultStyledDocument doc = null;


     public TestKeypad(){
          super();
          initComponents();
         
     }

     private void initComponents(){

        setTitle("Test input from Keypad");
        setSize(WIDTH, HEIGTH);

        JPanel content = (JPanel) getContentPane();
        content.setLayout( new GridLayout(2, 1, 5,5));

        //doc = new DefaultStyledDocument();
          typingArea = new JTextPane();
          typingArea.setBackground(Color.lightGray);
          typingArea.addKeyListener(this);

          displayArea = new JTextArea();
          //displayArea.setBackground(Color.gray);
          displayArea.disable();
          content.add(typingArea);
          content.add(displayArea);
       

     }

     public static void main (String arg[])
     {
          TestKeypad frame = new TestKeypad();
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          frame.setVisible(true);
     }


    // Key Listener implementation

    //I need user typing area have focus all the time
     public void keyPressed( KeyEvent event )
     {
       
        int myCode = event.getKeyCode();
        String myText = event.getKeyText(myCode);
        String removeExcess = event.getKeyText(event.getKeyCode());
        String typingAreaContent = "";          
        typingAreaContent = typingArea.getText();        
                 
        if (myCode >= 48 && myCode <=57) //numerals at top of keyboard
        {
            removeExcess = null;
            typingArea.setText(typingArea.getText().substring(0,typingArea.getText().length()-1));            
                     
        }
        else if (myCode >= 96 && myCode <=105)  //number pad numerals
        {
            removeExcess = removeExcess.replaceFirst("NumPad-", "");
            totalString = totalString + removeExcess;
            displayArea.setText (totalString);    
        }
        else if (myCode == 107 || myCode == 109) //number pad "+" and "-"
        {
            removeExcess = removeExcess.replaceFirst("NumPad", "");
            totalString = totalString + removeExcess;
            displayArea.setText (totalString);    
        }
       
                   
      }


      //I need forward the event to the user typing area.
      public void keyTyped( KeyEvent event )
      {
       
      }


      public void keyReleased( KeyEvent event )
      {
         
      }

}

         
0
 
LVL 10

Expert Comment

by:edwardiii
ID: 13912163
objects--why does the code below work only with the JOptionPanes firing in the midst of the keyPressed ?:

     public void keyPressed( KeyEvent event )
     {
       
        char key = event.getKeyChar();      
        int myCode = event.getKeyCode();
        String myText = event.getKeyText(myCode);
        String removeExcess = event.getKeyText(event.getKeyCode());
        String typingAreaContent = "";          
        typingAreaContent = typingArea.getText();        
                 
        if (myCode >= 48 && myCode <=57) //numerals at top of keyboard
        {
            removeExcess = null;            
            //typingArea.setText(typingArea.getText().substring(0,typingArea.getText().length()-1));            
            JOptionPane.showMessageDialog( null, "" + typingAreaContent, "Typing Area Content", JOptionPane.INFORMATION_MESSAGE );
            typingArea.setText(typingAreaContent);
            totalString = totalString + key;
            displayArea.setText (totalString);
           
        }
        else if (myCode >= 96 && myCode <=105)  //number pad numerals
        {
            //typingArea.setText(typingArea.getText().substring(0,typingArea.getText().length()-1));            
            JOptionPane.showMessageDialog( null, "" + typingAreaContent, "Typing Area Content", JOptionPane.INFORMATION_MESSAGE );
            typingArea.setText(typingAreaContent);
            removeExcess = removeExcess.replaceFirst("NumPad-", "");
            totalString = totalString + removeExcess;
            displayArea.setText (totalString);            
        }
        else if (myCode == 107 || myCode == 109) //number pad "+" and "-"
        {
            removeExcess = removeExcess.replaceFirst("NumPad", "");
            totalString = totalString + removeExcess;
            displayArea.setText (totalString);    
        }        
           
      }
0
 

Author Comment

by:SarahDeng
ID: 13912799

Hi edwardiii and object,

I simplified the code changed by edwardiii. The problem is still there, which can't remove numerics from the top typingArea, although I add event.consume() to consume them. (BTW, I don't need process the numbers from the top of keyboard differently, only keys from keypad will be displayed in the "displayArea").

Could you shed your light on this problem? Thanks.


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

public class TestKeypad extends JFrame implements KeyListener
{
     final static int WIDTH = 600;
     final static int HEIGTH = 500;
     private String totalString ="";
     //Text pane for user to type, it has the focus all the time
     private JTextPane typingArea;

     //Text field display numbers, it never has focus
     private JTextArea displayArea;

     //private DefaultStyledDocument doc = null;


     public TestKeypad(){
          super();
          initComponents();

     }

     private void initComponents(){

        setTitle("Test input from Keypad");
        setSize(WIDTH, HEIGTH);

        JPanel content = (JPanel) getContentPane();
        content.setLayout( new GridLayout(2, 1, 5,5));

        //doc = new DefaultStyledDocument();
          typingArea = new JTextPane();
          typingArea.setBackground(Color.lightGray);
          typingArea.addKeyListener(this);

          displayArea = new JTextArea();
          //displayArea.setBackground(Color.gray);
          displayArea.disable();
          content.add(typingArea);
          content.add(displayArea);


     }

     public static void main (String arg[])
     {
          TestKeypad frame = new TestKeypad();
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          frame.setVisible(true);
     }


    // Key Listener implementation

    //I need user typing area have focus all the time
     public void keyPressed( KeyEvent event )
     {
        String removeExcess = event.getKeyText(event.getKeyCode());

        if (event.getKeyCode() >= 96 && event.getKeyCode() <=105)  //number pad numerals
        {
                  event.consume();
            removeExcess = removeExcess.replaceFirst("NumPad-", "");
            totalString = totalString + removeExcess;
            displayArea.setText (totalString);
        }
        else if (event.getKeyCode() == 106 || event.getKeyCode() == 110) //number pad "*" and "."
        {
                  event.consume();
            removeExcess = removeExcess.replaceFirst("NumPad", "");
            totalString = totalString + removeExcess;
            displayArea.setText (totalString);
        }


      }


      //I need forward the event to the user typing area.
      public void keyTyped( KeyEvent event )
      {
        if (event.getKeyCode() >= 96 && event.getKeyCode() <=105)  //number pad numerals
        event.consume();

        if (event.getKeyCode() == 106 || event.getKeyCode() == 110) //number pad "*" and "."
        event.consume();
      }


      public void keyReleased( KeyEvent event )
      {

      }

}

0
 
LVL 10

Expert Comment

by:edwardiii
ID: 13913866
Hi, SarahDeng.

I was able to get my previous code to work by adding code to the keyReleased event.  I created a new int variable "keyedType"; if any type of numeric was entered then keyedType was set equal to 1,2, or 3, but if an Alpha was input then keyedType was set = 4.  In the keyReleased event I then entered:

     if (keyedType != 4)
          {    
               typingArea.setText(typingArea.getText().substring(0,typingArea.getText().length()-1));
          }

This now removes any numerals from the upper typingArea JTextPane:)  Here is the latest code:


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

public class TestKeypad extends JFrame implements KeyListener
{
     final static int WIDTH = 600;
     final static int HEIGTH = 500;    
     private String totalString ="";
     private int keyedType = 0;
     //Text pane for user to type, it has the focus all the time
     private JTextPane typingArea;

     //Text field display numbers, it never has focus
     private JTextArea displayArea;
     

     // The current keyboard focus manager
     //private KeyboardFocusManager kfm = null;

     //private DefaultStyledDocument doc = null;


     public TestKeypad(){
          super();
          initComponents();
         
     }

     private void initComponents(){

        setTitle("Test input from Keypad");
        setSize(WIDTH, HEIGTH);

        JPanel content = (JPanel) getContentPane();
        content.setLayout( new GridLayout(2, 1, 5,5));

        //doc = new DefaultStyledDocument();
          typingArea = new JTextPane();
          typingArea.setBackground(Color.lightGray);
          typingArea.addKeyListener(this);          
         
          displayArea = new JTextArea();
          //displayArea.setBackground(Color.gray);
          displayArea.disable();
          content.add(typingArea);
          content.add(displayArea);          
       
     }

     public static void main (String arg[])
     {
          TestKeypad frame = new TestKeypad();
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          frame.setVisible(true);
     }

    // Key Listener implementation

    //I need user typing area have focus all the time
     public void keyPressed( KeyEvent event )
     {
        //event.consume();
        char key = event.getKeyChar();      
        int myCode = event.getKeyCode();
        String myText = event.getKeyText(myCode);
        String removeExcess = event.getKeyText(event.getKeyCode());      
        String typingAreaContent = "";          
        typingAreaContent = typingArea.getText();        
                 
        if (myCode >= 48 && myCode <=57) //numerals at top of keyboard
        {
            removeExcess = null;
            keyedType = 1;            
            typingArea.setText(typingAreaContent);
            totalString = totalString + key;
            displayArea.setText (totalString);            
                       
        }
        else if (myCode >= 96 && myCode <=105)  //number pad numerals
        {
            keyedType = 2;
            typingArea.setText(typingAreaContent);
            removeExcess = removeExcess.replaceFirst("NumPad-", "");
            totalString = totalString + removeExcess;
            displayArea.setText (totalString);            
        }
        else if (myCode == 107 || myCode == 109) //number pad "+" and "-"
        {
            keyedType = 3;
            removeExcess = removeExcess.replaceFirst("NumPad", "");
            totalString = totalString + removeExcess;
            displayArea.setText (totalString);    
        }        
        else keyedType = 4;        
      }

      //I need forward the event to the user typing area.
      public void keyTyped( KeyEvent event )
      {
       
      }

      public void keyReleased( KeyEvent event )
      {
         
          if (keyedType != 4)
          {    
               typingArea.setText(typingArea.getText().substring(0,typingArea.getText().length()-1));
          }
      }

}
0
 

Author Comment

by:SarahDeng
ID: 13914093
Hi edwardiii,

  I tried your latest code. I see how it works. It is getting closer to work. However, there are two problems. One is when I hold a key of keypad,( e.g. I hold the NUMPAD 7) the typingArea and displayArea both will show serveral '7's. Another one is each time I type a number key, the typingArea shows on the number first and then was eaten/removed when the key is released, just the way as you coded.

  The actual requriement is that the typingArea should not see the key input from keypad. So I think the keyevent from keypad should be consumed when the key is pressed and typed, not keyReleased. My 'event.consume()' doesn't consume the keyevent from keypad. Do you have any idea how to get it work? Thanks.
0
 
LVL 10

Accepted Solution

by:
edwardiii earned 1800 total points
ID: 13914768
You are right:)  I tried putting the event.consume() in the keyTyped event, and it seems to do everything you're looking for, including forcing the top typingArea to ignore any numerals, whether input via single-clicks or by holding down a numeral key:)  Here is the revised code:

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

public class TestKeypad extends JFrame implements KeyListener
{
     final static int WIDTH = 600;
     final static int HEIGTH = 500;    
     private String totalString ="";
     private int keyedType = 0;
     //Text pane for user to type, it has the focus all the time
     private JTextPane typingArea;

     //Text field display numbers, it never has focus
     private JTextArea displayArea;
     

     // The current keyboard focus manager
     //private KeyboardFocusManager kfm = null;

     //private DefaultStyledDocument doc = null;


     public TestKeypad(){
          super();
          initComponents();
         
     }

     private void initComponents(){

        setTitle("Test input from Keypad");
        setSize(WIDTH, HEIGTH);

        JPanel content = (JPanel) getContentPane();
        content.setLayout( new GridLayout(2, 1, 5,5));

        //doc = new DefaultStyledDocument();
          typingArea = new JTextPane();
          typingArea.setBackground(Color.lightGray);
          typingArea.addKeyListener(this);          
         
          displayArea = new JTextArea();
          //displayArea.setBackground(Color.gray);
          displayArea.disable();
          content.add(typingArea);
          content.add(displayArea);          
       
     }

     public static void main (String arg[])
     {
          TestKeypad frame = new TestKeypad();
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          frame.setVisible(true);
     }

    // Key Listener implementation

    //I need user typing area have focus all the time
     public void keyPressed( KeyEvent event )
     {
        //event.consume();
        char key = event.getKeyChar();      
        int myCode = event.getKeyCode();
        String myText = event.getKeyText(myCode);
        String removeExcess = event.getKeyText(event.getKeyCode());      
        String typingAreaContent = "";          
        typingAreaContent = typingArea.getText();        
                 
        if (myCode >= 48 && myCode <=57) //numerals at top of keyboard
        {
            removeExcess = null;
            keyedType = 1;            
            typingArea.setText(typingAreaContent);
            totalString = totalString + key;
            displayArea.setText (totalString);            
                       
        }
        else if (myCode >= 96 && myCode <=105)  //number pad numerals
        {
            keyedType = 2;
            typingArea.setText(typingAreaContent);
            removeExcess = removeExcess.replaceFirst("NumPad-", "");
            totalString = totalString + removeExcess;
            displayArea.setText (totalString);            
        }
        else if (myCode == 107 || myCode == 109) //number pad "+" and "-"
        {
            keyedType = 3;
            removeExcess = removeExcess.replaceFirst("NumPad", "");
            totalString = totalString + removeExcess;
            displayArea.setText (totalString);    
        }        
        else keyedType = 4;        
      }

      //I need forward the event to the user typing area.
      public void keyTyped( KeyEvent event )
      {
          if (keyedType != 4)
          {    
              event.consume();
             
          }
      }

      public void keyReleased( KeyEvent event )
      {
                   
      }
0

Featured Post

Upgrade your Question Security!

Add Premium security features to your question to ensure its privacy or anonymity. Learn more about your ability to control Question Security today.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Java Flight Recorder and Java Mission Control together create a complete tool chain to continuously collect low level and detailed runtime information enabling after-the-fact incident analysis. Java Flight Recorder is a profiling and event collectio…
In this post we will learn how to connect and configure Android Device (Smartphone etc.) with Android Studio. After that we will run a simple Hello World Program.
This tutorial will introduce the viewer to VisualVM for the Java platform application. This video explains an example program and covers the Overview, Monitor, and Heap Dump tabs.
How to fix incompatible JVM issue while installing Eclipse While installing Eclipse in windows, got one error like above and unable to proceed with the installation. This video describes how to successfully install Eclipse. How to solve incompa…
Suggested Courses
Course of the Month18 days, 6 hours left to enroll

830 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question