#1
  1. Web Developer
    Devshed Novice (500 - 999 posts)

    Join Date
    Oct 2001
    Location
    Finland
    Posts
    719
    Rep Power
    19

    Weird delay in changing color in Jtextfield


    Hi everyone.

    I'm trying to add a small effect to the text in my Jtextfield component. The logic is simple; if the text in the field is a valid number, keep the text black, otherwise turn it red. I have the method written and it works, except there is a strange lag before the color changes.

    Not a time lag per say, but it always takes 2 invalid characters in the field, before it turns red. Turning back to black is as it should, the minute I erase the wrong characters, the color changes to black.

    Example:
    653.4 (stay black, as it should)
    653.4i (still stay black, although it should change)
    653.4ie (now it changes to red)

    Here's the code:
    java Code:
        private void quantityKeyTyped(java.awt.event.KeyEvent evt) {                                  
            Pattern pattern = Pattern.compile("^[0-9]+[.]?[0-9]*$");
            Matcher matcher = pattern.matcher(quantity.getText());
     
            if (matcher.find() || quantity.getText().equalsIgnoreCase("")) {
                quantity.setForeground(new Color(51,51,51));
            } else {
                quantity.setForeground(new Color(204,0,0));
            }
        }


    I can't figure what's wrong with my method. Any ideas?
    Last edited by Datamike; June 18th, 2007 at 02:59 PM.
    -- Tomi Kaistila
    -- Developer's Journal

    The more you learn, the more you know.
    The more you know, the more you forget.
    The more you forget, the less you know.
  2. #2
  3. No Profile Picture
    Clueless llama
    Devshed Regular (2000 - 2499 posts)

    Join Date
    Feb 2001
    Location
    Lincoln, NE. USA
    Posts
    2,353
    Rep Power
    121
    It appears that the keyTyped event is happening before the actual character is being entered into the JTextField. If you do a System.out.println() you will see that the value you are verifying with your Regular Expression is not what you think (Oddly enough, when you press backspace it DOES process the backspace and enter it into the text field before the keyTyped event handler. Very odd).

    Instead, you can process the actual char entered each time using the event.getKeyChar() method. However, this won't let you check for more than one dot(.) without some workarounds.

    There are other alternatives mentioned here
    http://java.sun.com/developer/JDCTec...01/tt1120.html


    Lastly, if you override the keyReleased method instead of the keyTyped, it appears to work as you intend. No idea if it will have any other weird side effects though.


    java Code:
     
    	public static void main(String[] args) {
    		JFrame frame = new JFrame("test changer");
    		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		JPanel panel = new JPanel();
    		final JTextField quantity = new JTextField(10);
    		panel.add(quantity);
     
    		quantity.addKeyListener(new KeyAdapter() {
    	        private Pattern pattern = Pattern.compile("^[0-9]+[.]?[0-9]*$");
    	    	private final Color RED = new Color(204,0,0);
    	    	private final Color BLACK = new Color(51,51,51);
     
    			public void keyReleased(KeyEvent e) {
    		        Matcher matcher = pattern.matcher(quantity.getText());
     
    		        System.out.println(quantity.getText());
    		        if (matcher.find() || quantity.getText().equalsIgnoreCase("")) {
    		            quantity.setForeground(BLACK);
    		        } else {
    		            quantity.setForeground(RED);
    		        }
    			}
    		});
     
    		frame.getContentPane().add(panel);
    		frame.pack();
    		frame.setVisible(true);
    	}

    Comments on this post

    • Yawmark agrees
    Last edited by Nemi; June 18th, 2007 at 07:58 PM.
    ~Nemi

    Before posting did you try:
    [ Javadocs | Google ]
  4. #3
  5. Web Developer
    Devshed Novice (500 - 999 posts)

    Join Date
    Oct 2001
    Location
    Finland
    Posts
    719
    Rep Power
    19
    Thanks Nemi, that got it working, and also gave me ideas for improvement
    -- Tomi Kaistila
    -- Developer's Journal

    The more you learn, the more you know.
    The more you know, the more you forget.
    The more you forget, the less you know.
  6. #4
  7. Feelin' Groovy
    Devshed Supreme Being (6500+ posts)

    Join Date
    Aug 2001
    Location
    Chicago, IL
    Posts
    10,131
    Rep Power
    5057
    There are other alternatives mentioned here...
    One of the alternatives is the JFormattedTextField, which is now way past the beta stage mentioned in the article and is what I'd encourage the OP to look at as a solution. Thanks for the article, Nemi!

    ~
    Yawmark
    class Sig{public static void main(String...args){\u0066or(int
    \u0020$:"v\"ʲ\"vΤ\"".to\u0043h\u0061rArray()
    )System./*goto/*$/%\u0126//^\u002A\u002Fout.print((char)(($>>
    +(~'"'&'#'))+('<'>>('\\'/'.')/\u002Array.const(~1)\*\u002F)));}}
  8. #5
  9. No Profile Picture
    Clueless llama
    Devshed Regular (2000 - 2499 posts)

    Join Date
    Feb 2001
    Location
    Lincoln, NE. USA
    Posts
    2,353
    Rep Power
    121
    Originally Posted by Yawmark
    One of the alternatives is the JFormattedTextField, which is now way past the beta stage mentioned in the article and is what I'd encourage the OP to look at as a solution.
    I saw this but only briefly looked into it, leaving it up to Datamike to check it out. Today I tried it and it is pretty easy to get it to work. At its simplest, you pass a Numberformat object and when the field loses focus, it formats the input to a number for you. No muss, no fuss.

    java Code:
     
    	public static void main(String[] args) {
    		JFrame frame = new JFrame("test changer");
    		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		JPanel panel = new JPanel();
    		JFormattedTextField quantity = new JFormattedTextField(NumberFormat
    				.getInstance());
    		quantity.setColumns(10);
    		panel.add(quantity);
    		JButton button = new JButton("Dummy Button");
    		panel.add(button);		
     
    		button.addActionListener(new ActionListener() {
    			public void actionPerformed(ActionEvent e) {
    				System.out.println(quantity.getValue());
    			}
    		});
     
    		frame.getContentPane().add(panel);
    		frame.pack();
    		frame.setVisible(true);
     
    	}



    Thanks Yawmark!



    EDIT: changed code slightly. Use getValue instead of getText and it will return a Long class or a Double class.

    Comments on this post

    • valined agrees : Great posts, Nemi!
    Last edited by Nemi; June 19th, 2007 at 09:57 AM.
    ~Nemi

    Before posting did you try:
    [ Javadocs | Google ]

IMN logo majestic logo threadwatch logo seochat tools logo