Question

Completely New Direction

Following is the SSCCE of my issue. I'm trying to get the fields to update as input is being entered, in this case focus MUST be lost for an update to occur.

package test;
import java.awt.EventQueue;
import java.text.NumberFormat;
import javax.swing.JFormattedTextField;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.Document;
import javax.swing.text.NumberFormatter;

public class Test {

    private JFormattedTextField input, input2;
    private NumberFormatter formatter;
    private DocumentListener listener;

    public Test() {
        formatter = new NumberFormatter(NumberFormat.getNumberInstance());
        input = new JFormattedTextField(formatter);
        input2 = new JFormattedTextField(formatter);

        listener = new DocumentListener() {

            private Document source = null;

            protected void update(Document doc) {
                if (source == null) {
                    System.out.println("Update");
                    source = doc;
                    if (source.equals(input.getDocument())) {
                        double temp;
                        temp = converter(((Number)input.getValue()).doubleValue());
                        input2.setValue(temp);
//                        input2.setText(Double.toString(temp));
                    } else if (source.equals(input2.getDocument())) {                       
                        double temp;
                        temp = converterBack(((Number)input2.getValue()).doubleValue());
                        input.setValue(temp);
//                        input.setText(Double.toString(temp));
                    }
                    source = null;
                }
            }

            @Override
            public void insertUpdate(DocumentEvent e) {
                update(e.getDocument());
            }

            @Override
            public void removeUpdate(DocumentEvent e) {
                update(e.getDocument());
            }

            @Override
            public void changedUpdate(DocumentEvent e) {
                update(e.getDocument());
            }
        };

        input.getDocument().addDocumentListener(listener);
        input2.getDocument().addDocumentListener(listener);
        input.setColumns(4);
        input2.setColumns(4);
        input.setValue(0.0);
        JPanel panel = new JPanel();
        panel.add(input);
        panel.add(input2);

        JOptionPane.showMessageDialog(null, panel);
    }

    public static void main(String[] args) {

        EventQueue.invokeLater(new Runnable() {
            public void run() {
                new Test();
            }
        });

    }

    private double converter(double value) {
        value = value * 2;

        return value;
    }
    private double converterBack(double value){
        value = value/2;
        
        return value;
    }
}

I need to be able to utilize this code with a 'converter' method, so putting the commands into the method Update() isn't an option.

I have gotten this to work with PropertyChangeListener but apparently it's not a good route to take.

Was it helpful?

Solution

A PropertyChangeListener isn't going to work for this problem, as the field's Document won't raise events...The Document is a property of the field, but it's contents is not.

A better solution would be to use a DocumentListener. This will notify when the underlying document contents has changed.

You need to be careful with this, as a Document does not like been changed while it's already undergoing a change.

In this example, I use the source Document of the event and compare it to each fields Document to determine what should be updated...

Example

import java.awt.EventQueue;
import java.beans.PropertyChangeEvent;
import java.text.NumberFormat;
import javax.swing.JFormattedTextField;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.Document;
import javax.swing.text.NumberFormatter;

public class Test {

    private JFormattedTextField input, input2;
    private NumberFormatter formatter;
//    private PropertyChangeListener listener;
    private DocumentListener listener;

    public Test() {
        formatter = new NumberFormatter(NumberFormat.getNumberInstance());
        input = new JFormattedTextField(formatter);
        input2 = new JFormattedTextField(formatter);

        listener = new DocumentListener() {

            private Document source = null;

            protected void update(Document doc) {
                if (source == null) {
                    System.out.println("Update");
                    source = doc;
                    if (source.equals(input.getDocument())) {
                        input2.setText(input.getText());
                    } else if (source.equals(input2.getDocument())) {
                        input.setText(input2.getText());
                    }
                    source = null;
                }
            }

            @Override
            public void insertUpdate(DocumentEvent e) {
                update(e.getDocument());
            }

            @Override
            public void removeUpdate(DocumentEvent e) {
                update(e.getDocument());
            }

            @Override
            public void changedUpdate(DocumentEvent e) {
                update(e.getDocument());
            }
        };
//        listener = new PropertyChangeListener() {
//            @Override
//            public void propertyChange(PropertyChangeEvent evt) {
//                convert(evt);
//            }
//        };

        input.getDocument().addDocumentListener(listener);
        input2.getDocument().addDocumentListener(listener);

        input.setColumns(4);
        input2.setColumns(4);
//        input.addPropertyChangeListener("value", listener);
//        input2.addPropertyChangeListener("value", listener);
        input.setValue(0.0);
        JPanel panel = new JPanel();
        panel.add(input);
        panel.add(input2);

        JOptionPane.showMessageDialog(null, panel);
    }

    private void convert(PropertyChangeEvent evt) {
        if (evt.getSource() == input) {
            if (evt.getSource() != null) {
                double temp;
                temp = converter((Double) evt.getNewValue());
                input2.setValue(temp);
            }

        }

    }

    public static void main(String[] args) {

        EventQueue.invokeLater(new Runnable() {
            public void run() {
                new Test();
            }
        });

    }

    private double converter(double value) {
        value = value * 2;

        return value;
    }

}

Updated

The problem you're having with your conversion is the fact that the value has not yet been "committed", meaning it has not been validated and the value property has not yet been changed.

Calling getValue will return the last committed value.

What you need to do is commit the edit first...

if (source.equals(input.getDocument())) {
    try {
        input.commitEdit();
        double temp = ((Number) input.getValue()).doubleValue();
        temp = converter(temp);
        input2.setValue(temp);
    } catch (ParseException ex) {
    }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top