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.
CodePudding user response:
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...
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)
CodePudding user response:
Madprogrammer posted a very fine example of reacting to every document change. If instead you are just interested in the field value (length) when the user hits enter, attach an ActionListener. Of course you can make use of other objects or the content of your TextField in ActionListeners.
Use the ActionEvent.getSource() (inherited from EventObject) method. And be aware if you are using an ActionListener for other stuff already, there is no problem in attaching several listeners for the same event.