Domanda

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.

È stato utile?

Soluzione

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();
            }
        });
    }
}

Altri suggerimenti

int p=0;
try {
    p = Integer.parseInt(text);
}
catch (NumberFormatException ex) {
    //define here which number should be shown when input is incorrect. e.g. p=0;
}

You can wrap the value parsing and provide proper output for the case when source value can't be parsed correctly.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top