简体   繁体   中英

Make program “pause” until the user enters something in a JTextField

I'm tying to make a program that acts similar to the Windows Command Prompt, or a terminal. It's basically just a JFrame with a JTextArea as output , and a JTextField as input . It looks like this:

在此处输入图片说明

I want to be able to get input from the JTextField whenever my program calls a method that returns a String, something like:

public static String getInput() {
    //Wait for user to enter something, then press the enter key
}

I added an AbstractAction so I can do stuff when the enter key is pressed, but I still could figure out how to return the input as a String whenever I call the method.

Action action = new AbstractAction(){
    @Override
    public void actionPerformed(ActionEvent e) {

        //Clears the JTextField
        input.setText("");

    }
};

I could put something like userInput = input.getText() in public void actionPerformed() , so it would just set a variable to whatever has been entered every time, and use userInput whenever I want to, but I want the user to have time to read whats on the screen, then have the program wait for a response, instead of just using the last thing they entered right away.

I tried to use a userInput variable and a boolean variable like this:

private static String userInput = "";
private static boolean enterPressed = false;

Action action = new AbstractAction(){
    @Override
    public void actionPerformed(ActionEvent e) {

        userInput = input.getText()
        enterPressed = true;
        input.setText("");

    }
};

...

public static String getInput() {

    enterPressed = false;
    while(!enterPressed){
       //Do Nothing
    }
    enterPressed = false;
    return userInput;

}

When I called output.setText(getInput()); , it worked like I wanted to, except that the while(!enterPressed){} made my processor work a lot harder than it should need to. I'm pretty sure there's probably a lot better way of doing this.

Here's my whole code right now:

public class ConsoleFrame {

//Objects for Console Frame
JFrame frame = new JFrame();
JTextArea output = new JTextArea();
JTextField input = new JTextField();
BoxLayout boxLayout = new BoxLayout(frame.getContentPane(), BoxLayout.Y_AXIS);
JScrollPane scrollPane = new JScrollPane(output);
DefaultCaret caret = (DefaultCaret)output.getCaret();
Action action = new AbstractAction(){
    @Override
    public void actionPerformed(ActionEvent e) {

        input.setText("");

    }
};
ConsoleFrame(){
    input.addActionListener(action);
    caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
    frame.setLayout(boxLayout);
    frame.add(scrollPane);
    frame.add(input);
    frame.pack();
    frame.setVisible(true);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(500, 250);
    frame.setLocationRelativeTo(null);
    input.setMaximumSize(new Dimension(Integer.MAX_VALUE, 10));
    output.setEditable(false);
    output.setAutoscrolls(true);
}
public static String getInput() {
    return null;
}

}

So, how could I stop the program until the user presses enter, every time I call getInput(); ?

EDIT: First half removed. It was brought to my attention that it was erroneous.

The best option is to enclose a call to whatever you need your computer to execute after the user inputs text inside your actionPerformed method. So when the user inputs text and presses enter, the program automatically continues from there.

Action action = new AbstractAction(){
@Override
    public void actionPerformed(ActionEvent e) {

    userInput = input.getText()
    enterPressed = true;
    input.setText("");
    //call next method;

    }
};

This requires some more formatting work on your behalf, but it could be helpful depending on your project. This link has more information on this strategy.

Hope this helped.

I want to be able to get input from the JTextField whenever my program calls a method that returns a String, something like:

I added an AbstractAction so I can do stuff when the enter key is pressed, but I still could figure out how to return the input as a String whenever I call the method.

public String getInput() {
    return input.getText();
}

So, how could I stop the program until the user presses enter, every time I call getInput();?

You don't. Swing, like most UI frame works is event driven, that is, something happens and your respond to it.

So, with that in mind you should consider using some kind Observer Pattern , where you use a call back to be notified of some kind of change which you are interested in, like your ActionListener for example.

Instead, you could provide some kind of listener, which interested parties would register with and when the field changes you would notify them, for example...

import java.util.EventListener;
import java.util.EventObject;

public class InputEvent extends EventObject {

    private final String text;

    public InputEvent(Object source, String text) {
        super(source);
        this.text = text;
    }

    public String getText() {
        return text;
    }

}

public interface InputObsever extends EventListener {

    public void inputChanged(InputEvent evt);

}

So, we now have an observer who will be notified when ever the input is changed/updated.

Then we simply need a way to un/register and fire the event...

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.event.EventListenerList;
import javax.swing.text.DefaultCaret;

public class ConsoleFrame {

//Objects for Console Frame
    JFrame frame = new JFrame();
    JTextArea output = new JTextArea();
    JTextField input = new JTextField();
    BoxLayout boxLayout = new BoxLayout(frame.getContentPane(), BoxLayout.Y_AXIS);
    JScrollPane scrollPane = new JScrollPane(output);
    DefaultCaret caret = (DefaultCaret) output.getCaret();
    Action action = new AbstractAction() {
        @Override
        public void actionPerformed(ActionEvent e) {

            fireInputChanged(input.getText());
            input.selectAll();

        }
    };

    private EventListenerList listenerList = new EventListenerList();

    ConsoleFrame() {
        input.addActionListener(action);
        caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
        frame.setLayout(boxLayout);
        frame.add(scrollPane);
        frame.add(input);
        frame.pack();
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(500, 250);
        frame.setLocationRelativeTo(null);
        input.setMaximumSize(new Dimension(Integer.MAX_VALUE, 10));
        output.setEditable(false);
        output.setAutoscrolls(true);
    }

    public String getInput() {
        return input.getText();
    }

    public void addInputObsever(InputObsever obsever) {
        listenerList.add(InputObsever.class, obsever);
    }

    public void removeInputObsever(InputObsever obsever) {
        listenerList.remove(InputObsever.class, obsever);
    }

    protected void fireInputChanged(String text) {

        InputObsever[] listeners = listenerList.getListeners(InputObsever.class);
        if (listeners.length > 0) {

            InputEvent evt = new InputEvent(this, text);
            for (InputObsever obsever : listeners) {
                obsever.inputChanged(evt);
            }

        }

    }

}

Now, the point here is, when you want to know when the text has been input/changed, you register an observer to the instance of the ConsoleFrame

console.addInputObsever(new InputObsever() {
    @Override
    public void inputChanged(InputEvent evt) {
        // Do what ever you need to do...
    }
});
    jTextField1.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
                yourFunction(jTextField1.getText());
                jTextField1.setText("");
        }
    });

Btw just a tip, you may append the JTextArea to get the feel of a console window

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