Search code examples
javaswingjtextfielddocumentlistener

synchronize jtextfield value into only integer value using document listener


Following the Question Synchronize JTextField values by property change listener

I have tried to modify the example from the answer using document listener. What I wanted to modify was to synchronize only integers. For example, if I put '2' in field1 then it would multiply by '5' so that the value would be '10' in the field2. However, I have followed various methods but I am having some errors such as:

Exception in thread "AWT-EventQueue-0" java.lang.NumberFormatException: For input string: ""

Moreover, when I delete all values from field1, the last synchronized field2 value remains whereas field2 also supposed to be null as field1. I am not sure which part I have made mistake. Here is my code sample for the UpdateLabel Method:

private void updateLabel(DocumentEvent e) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            String text = field.getText();
            String text1 = field1.getText();
        @Override
        public void run() {
            if(text == null && text1 != null){field1.setText(null);
            }else 
                if(text.contains("-") ||
                   text.contains(".") ||
                   text.matches(".*[a-zA-Z].*")|| 
                   text.matches(".*\\p{Punct}.*")){
                   {JOptionPane.showMessageDialog(frame = new JFrame(),
                   "Please put appropriate int value from 0-9",
                   "Inane error",
                   JOptionPane.ERROR_MESSAGE);
                   field.setText(null);
                   field1.setText(null);
                   }
                }else{
                    int p;
                    p = Integer.parseInt(text);
                    int i = (p*5);
                    String s = String.valueOf(i);
                    field1.setText(s);
                    }
        }
   });
}

I also want to use the '.' with integers but when I removetext.contains(".") it still shows JOptionPane error message.


Solution

  • You're getting NumberFormatException because nothing can't be converted to a number, when you clear the text from field so you need to check if the field is empty.

    if (!text.isEmpty()) {
        int p = Integer.parseInt(text);
        int i = (p * 5);
        String s = String.valueOf(i);
        field1.setText(s);
    } else {
        field1.setText(null);
    }
    

    Also as I noted in the comments, with links, just use a DocumentFilter allow only numbers.

    Here is a refactor of your code. It works without the NumberFormatException. I added the DocumentFilter

    import java.awt.GridLayout;
    import javax.swing.*;
    import javax.swing.event.DocumentEvent;
    import javax.swing.event.DocumentListener;
    import javax.swing.text.AbstractDocument;
    import javax.swing.text.AttributeSet;
    import javax.swing.text.BadLocationException;
    import javax.swing.text.DocumentFilter;
    import javax.swing.text.DocumentFilter.FilterBypass;
    
    public class TestLabelMirror {
    
        private JPanel mainPanel = new JPanel();
        private JTextField field = new JTextField(20);
        private JTextField field1 = new JTextField(20);
        private JFrame frame;
    
        public TestLabelMirror() {
            field.getDocument().addDocumentListener(new DocumentListener() {
                @Override
                public void changedUpdate(DocumentEvent e) {
                    updateLabel(e);
                }
    
                @Override
                public void insertUpdate(DocumentEvent e) {
                    updateLabel(e);
                }
    
                @Override
                public void removeUpdate(DocumentEvent e) {
                    updateLabel(e);
                }
    
                private void updateLabel(DocumentEvent e) {
                    java.awt.EventQueue.invokeLater(new Runnable() {
                        public void run() {
                            String text = field.getText();
                            String text1 = field1.getText();
    
                            if (!text.isEmpty()) {
                                int p = Integer.parseInt(text);
                                int i = (p * 5);
                                String s = String.valueOf(i);
                                field1.setText(s);
                            } else {
                                field1.setText(null);
                            }
    
                        }
    
                    });
                }
            });
            ((AbstractDocument) field.getDocument()).setDocumentFilter(new DocumentFilter() {
                @Override
                public void insertString(FilterBypass fb, int off, String str, AttributeSet attr)
                        throws BadLocationException {
                    fb.insertString(off, str.replaceAll("\\D++", ""), attr);  // remove non-digits
                }
    
                @Override
                public void replace(FilterBypass fb, int off, int len, String str, AttributeSet attr)
                        throws BadLocationException {
                    fb.replace(off, len, str.replaceAll("\\D++", ""), attr);  // remove non-digits
                }
            });
    
            mainPanel.setLayout(new GridLayout(1, 0, 10, 0));
            mainPanel.add(field);
            mainPanel.add(field1);
        }
    
        public JComponent getComponent() {
            return mainPanel;
        }
    
        private static void createAndShowUI() {
            JFrame frame = new JFrame("TextLabelMirror");
            frame.getContentPane().add(new TestLabelMirror().getComponent());
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        }
    
        public static void main(String[] args) {
            java.awt.EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    createAndShowUI();
                }
            });
        }
    }