Search code examples
javasettextjformattedtextfieldselectall

JFormattedTextfield.selectAll() does not work when formatting the text


I have a lot of different JFormattedTextFields with action and keylisteners. Every Field has a keylistener, so when I press enter I will focus the next JFormattedTextField. The Problem is, for some JFormattedTextFields my code is formatting the input and then sets the text new and for those selectAll() does not work.

JFormattedTextField a = new JFormattedTextField(someDouble);
JFormattedTextField b = new JFormattedTextField(someDouble2);
a.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            leasingfaktor1Field.selectAll();
            if(...) {
                //do something
                a.setText(tausenderPunkt(someValue));
            }   
        }
    });
a.addKeyListener(new KeyAdapter() {
        public void keyPressed(KeyEvent e) {
            if (e.getKeyCode() == 10) {
                b.requestFocusInWindow();
            }
        }
    });
b.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            leasingfaktor1Field.selectAll();
            if(...) {
                //do something
                b.setText(tausenderPunkt(someValue));
            }   
        }
    });
b.addKeyListener(new KeyAdapter() {
        public void keyPressed(KeyEvent e) {
            if (e.getKeyCode() == 10) {
                c.requestFocusInWindow();
            }
        }
    });

The function tausenderPunkt():

public String tausenderPunkt(double value) {
    String s = String.format("%1$,.2f", value);
    return s;
}

So when my cursor is in field a and i press enter the cursor goes to field b but does not select the text or values. When i do not use setText() i do not have the problem. Somebody has a solution?

Edit: For some JFormattedTextFields the solution was to add selectAll() to the keyAdapter, but not for all. For example:

b.addKeyListener(new KeyAdapter() {
        public void keyPressed(KeyEvent e) {
            if (e.getKeyCode() == 10) {
                c.requestFocusInWindow();
                c.selectAll();
            }
        }
    });

Edit2: The problem seems to be when i create the JFormattedTextFields. When i do not create them with a value in the constructor it works. But i have to do.


Solution

  • Before moving to your next text field you should consider handling all the required conditions for the text field you are currently focused on and this would of course include the formatting of values or text supplied to that field. Once all the desired conditions are met then move on to the next text field.

    In reality this can all be accomplished through the keyPressed event for your particular situation. There is no need for the actionPerformed event on any of your text fields, for example:

    a.addKeyListener(new KeyAdapter() {
        @Override
        public void keyPressed(KeyEvent e) {
            if (e.getKeyCode() == KeyEvent.VK_ENTER) {
                checkConditions(a, b);
            }
        }
    });
    
    b.addKeyListener(new KeyAdapter() {
        @Override
        public void keyPressed(KeyEvent e) {
            if (e.getKeyCode() == KeyEvent.VK_ENTER) {
                checkConditions(b, c);
            }
        }
    });
    //----------  and so on  -------------
    

    Here is a simple method so as to eliminate the need for repetitious code:

    private void checkConditions(JFormattedTextField fieldA, JFormattedTextField fieldB) {
        // Make sure something is contained within fieldA and 
        // that it's actually numerical text.
        if(!fieldA.getText().isEmpty() && 
                    fieldA.getText().matches("([-]?)\\d+([,]\\d+)?(([.]\\d+)?)")) {
            // Convert the supplied text to Double and
            // ensure the desired numerical formating.
            String res = (String)tausenderPunkt(Double.parseDouble(fieldA.getText().replace(",","")));
            fieldA.setText(res);
            // Set Focus to our next text fieldB.
            fieldB.requestFocusInWindow();
            // Highlight the contents (if any) within the
            // next text fieldB.
            fieldB.selectAll();
        }
        // If fieldA is empty or fieldA does not contain 
        // numerical text then inform User and re-highlight
        // the entry in fieldA.
        else {
            JOptionPane.showMessageDialog (null, "Please Enter Numerical Values Only!", 
                    "Incorrect Entry", JOptionPane.WARNING_MESSAGE);
            fieldA.selectAll();
        }
    }
    

    If you want the contents of your first text field to be highlighted as soon as focus has been established upon it (tabbed to or clicked on) then consider using a FocusGained event for that component or any other component where you desire the same effect.

    I Hope this has helped in some way.

    EDITED!

    So as to handle OP's particular situation.