简体   繁体   中英

Action listener for a JTextField to change value in another textfield

I have two JTextfields, I want the value/text of second Textfield to change based on any change in value/text made in first TextField

Here is what I am doing

    textField_15 = new JTextField("100");
    textField_15.setEditable(false);
    textField_15.setColumns(10);
    textField_15.setBounds(161, 253, 86, 20);
    panel_3.add(textField_15);

    textField_14 = new JTextField();
    textField_14.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent arg0) {
            int az = Integer.parseInt(textField_14.getText());
            int aw = Integer.parseInt(textField_15.getText());
            int aq = aw - az;
            String ar = String.valueOf((aq));
            JOptionPane.showMessageDialog(null, az + " " +aw + " " + aq + " " + ar);
            textField_15.setText(ar);
        }
    });
    textField_14.setColumns(10);
    textField_14.setBounds(426, 186, 86, 20);
    panel_3.add(textField_14);

I'm assuming that you don't understand that ActionListener will only be notified when the user presses the Enter key...

That would be the easiest solution, if, however, you want to monitor changes to a text component, you should use a DocumentListener

See How to Use Text Fields , How to Write an Action Listeners and Listening for Changes on a Document for more details

This, however, raises some issues. When do you assume the user has stopped typing?

There is a significant difference between 100 and 1 and 0 and 0 , so what we need is someway to defer the event notification to some time in the future, where we can "assume" that the user has stopped typing (or at least long enough for us to grab a reasonable value)

public class DeferredDocumentChangedListener implements DocumentListener {

    private Timer timer;
    private List<ChangeListener> listeners;

    public DeferredDocumentChangedListener() {

        listeners = new ArrayList<>(25);
        timer = new Timer(250, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                fireStateChanged();
            }
        });
        timer.setRepeats(false);
    }

    public void addChangeListener(ChangeListener listener) {
        listeners.add(listener);
    }

    public void removeChangeListener(ChangeListener listener) {
        listeners.remove(listener);
    }

    protected void fireStateChanged() {
        if (!listeners.isEmpty()) {
            ChangeEvent evt = new ChangeEvent(this);
            for (ChangeListener listener : listeners) {
                listener.stateChanged(evt);
            }
        }
    }

    @Override
    public void insertUpdate(DocumentEvent e) {
        timer.restart();
    }

    @Override
    public void removeUpdate(DocumentEvent e) {
        timer.restart();
    }

    @Override
    public void changedUpdate(DocumentEvent e) {
        timer.restart();
    }

}

Okay, so, this is a little trick. This is a simple observable DocumentListener , which provides event notification at some point in the future that the document has changed. In your case, you don't really care about the change, just that it has.

This sets up a non-repeating Swing Timer with a short delay (250 milliseconds in the example) which if it's not reset for that period of time, will notify any registered ChangeListener s. If, however, the Document is modified within that time period, the Timer is reset.

You may want to play around with the "time out" value ;)

Which you could then use something like...

总结一下

JTextField number = new JTextField(5);
JTextField sum = new JTextField("0", 5);

setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;

add(number, gbc);
add(sum, gbc);

DeferredDocumentChangedListener listener = new DeferredDocumentChangedListener();
listener.addChangeListener(new ChangeListener() {

    @Override
    public void stateChanged(ChangeEvent e) {
        int num1 = Integer.parseInt(number.getText());
        int num2 = Integer.parseInt(sum.getText());
        int result = num1 + num2;
        sum.setText(Integer.toString(result));
        number.selectAll();
    }
});

number.getDocument().addDocumentListener(listener);

This, obviously doesn't provide any validation, so it could throw an exception if the text is not a number, but I'll leave that for you to figure out

You may also want to have a look at How to Use Spinners and How to Use Formatted Text Fields which provide post validation process which can help validate the user input.

You could also use a DocumentFilter to further restrict what the user can enter, see Implementing a Document Filter and DocumentFilter Examples for more details

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM