How can I print the text entered in a text field while the program runs?

Here is the code I currently have:

public String getLength()
    {
        return lengthEntry.getText();
    }

And in another class:

public class Main {
    
    public static void main(String[] args) {
        GUI userInterface = new GUI();
        System.out.print(userInterface.getLength());
    }
}

This is just a single print statement though, so it only prints the initial value of whatever is in the text field, nothing after. Is there a way I could write a loop in the main method that, while the program is running, prints the value in the text field when the user hits enter? I know I could put the print statement in the actionPerformed method, but then what’s the point of the getLength() method if I can’t use an object in another class to call it and get relevant information at any point when the program is running? I’m just looking for the pseudocode, it doesn’t have to compile or anything.

Answer

At a very basic level, you’re operating in an event driven environment. That is, something happens and you react to it.

Swing utilises the “observer pattern” to allow interested parties to be notified when something happens. This is a pretty common pattern.

In your case, I would “suggest” that you add a DocumentListener to the JTextField‘s Document and when it’s changed, you trigger a notification to the interested parties that the text count has changed, for example…

Simple event notification

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.util.EventListener;
import java.util.EventObject;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

public class Test extends JFrame {
    public static void main(String[] args) {
        new Test();
    }
    
    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                
                TextPane textPane = new TextPane();
                StatusPane statusPane = new StatusPane();
                textPane.addTextLengthListener(new TextLengthListener() {
                    @Override
                    public void textLengthDidChange(TextLengthEvent event) {
                        statusPane.setCount(event.getLength());
                    }
                });
                
                JFrame frame = new JFrame();
                frame.add(textPane);
                frame.add(statusPane, BorderLayout.SOUTH);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }
    
    public class TextLengthEvent extends EventObject {
        
        private int length;
        
        public TextLengthEvent(Object source, int length) {
            super(source);
            this.length = length;
        }

        public int getLength() {
            return length;
        }
        
    }
    
    public interface TextLengthListener extends EventListener {
        public void textLengthDidChange(TextLengthEvent event);
    }
    
    public class TextPane extends JPanel {
        
        private JTextField field;
        
        public TextPane() {
            setLayout(new GridBagLayout());
            setBorder(new EmptyBorder(8, 8, 8, 8));
            
            field = new JTextField(40);
            add(field);
            
            field.getDocument().addDocumentListener(new DocumentListener() {
                @Override
                public void insertUpdate(DocumentEvent e) {
                    fireTextLengthDidChange();
                }

                @Override
                public void removeUpdate(DocumentEvent e) {
                    fireTextLengthDidChange();
                }

                @Override
                public void changedUpdate(DocumentEvent e) {
                    fireTextLengthDidChange();
                }
            });
        }

        public JTextField getField() {
            return field;
        }
        
        public void addTextLengthListener(TextLengthListener listener) {
            listenerList.add(TextLengthListener.class, listener);
        }
        
        public void removeTextLengthListener(TextLengthListener listener) {
            listenerList.remove(TextLengthListener.class, listener);
        }
        
        protected void fireTextLengthDidChange() {
            TextLengthListener[] listeners = listenerList.getListeners(TextLengthListener.class);
            if (listeners.length == 0) {
                return;
            }
            
            TextLengthEvent evt = new TextLengthEvent(this, getField().getText().length());
            for (TextLengthListener listener : listeners) {
                listener.textLengthDidChange(evt);
            }
        }
        
    }
    
    protected class StatusPane extends JPanel {
        
        private JLabel label;

        public StatusPane() {
            setLayout(new GridBagLayout());
            setBorder(new EmptyBorder(8, 8, 8, 8));
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.anchor = GridBagConstraints.EAST;
            gbc.weightx = 1;
            
            label = new JLabel("0");
            add(label, gbc);
        }

        public JLabel getLabel() {
            return label;
        }
        
        public void setCount(int count) {
            getLabel().setText(Integer.toString(count));
        }
        
    }
}

This is a pretty basic example, which demonstrates

  • Decoupling of the code
  • Separation of responsibilities
  • Observer pattern (implement via the “listener” mechanism in Swing)