4

I'm a relatively new Java programmer (about two months experience) and I can't figure out how to get the data inputted into a Lanterna (a library for creating terminal user interfaces) textbox into a string for later use.

Here is my code:

//Variables (that I can't seem to populate)
final String usernameIn = null;
final String passwordIn = null;

//Username panel, contains Label and TextBox
Panel username = new Panel(new Border.Invisible(), Panel.Orientation.HORISONTAL);
username.addComponent(new Label("Username: "));
username.addComponent(new TextBox(null, 15));
addComponent(username);

//Password panel, contains label and PasswordBox
Panel password = new Panel(new Border.Invisible(), Panel.Orientation.HORISONTAL);
password.addComponent(new Label("Password: "));
password.addComponent(new PasswordBox(null, 15));
addComponent(password);

//Controls panel, contains Button w/ action
Panel controls = new Panel(new Border.Invisible(), Panel.Orientation.HORISONTAL);
controls.addComponent(new Button("Login", new Action()
{
    public void doAction() {
        MessageBox.showMessageBox(getOwner(), "Alert", "You entered the username " + usernameIn + " and password " + passwordIn + ".");
    }
}));
addComponent(controls);

Any help would be really appreciated. I have looked all over for information but there really isn't much on Lanterna and it's the only up-to-date Java library that I could find allowing me to make terminal applications. Please note: I'm aware there's nothing in the above code that'll process the inputted data, I left out all of my attempts as they caused pages upon pages of errors (which is to be expected when using the wrong functions).

3 Answers3

2

I got a look into the Lanterna code: TextBox has a getText() method.

As an idea:

Panel username = new Panel(new Border.Invisible(), Panel.Orientation.HORISONTAL);
username.addComponent(new Label("Username: "));
TextBox userBox = new TextBox(null, 15);
username.addComponent(userBox);
addComponent(username);
// ... and later elsewhere 
usernameIn = userBox.getText();

Shure, you need a reference to userBox to get the content later elsewhere in your code.

Lanterna has also a ComponentListener interface to response if a value changed:

Panel username = new Panel(new Border.Invisible(), Panel.Orientation.HORISONTAL);
username.addComponent(new Label("Username: "));
TextBox userBox = new TextBox(null, 15);
userBox.addComponentListener(new ComponentListener() {
    void onComponentValueChanged(InteractableComponent component) {
         usernameIn = ((TextBox)component).getText();
    }
});

username.addComponent(userBox);
addComponent(username);

That seems even cleaner.

PeterMmm
  • 24,152
  • 13
  • 73
  • 111
0

There are no addComponent() method in TextBox class, Lanterna ver3.0.0-beta2. So use readInput() in Screen. Below sample represent when user press enter, get text from TextBox.

private Screen screen;
private TextBox textBox; 
private final String emptyString = "";
...
public String getText() throws IOException {
    String result = null;
    KeyStroke key = null;
    while ((key = screen.readInput()).getKeyType() != KeyType.Enter) {
        textBox.handleKeyStroke(key);
       // use only one of handleInput() or handleKeyStroke() 
        textBox.setText(textBox.getText()); 
    }
    result = textBox.getText();
    textBox.setText(emptyString);
    return result;
0

One solution is to extend TextBox and override handleKeyStroke such that the TextBox itself initiates whatever action you wish to occur once the user hits Enter. This is useful if the flow of your program would make it inconvenient or impossible to manually handle inputs in your main thread. For example, this could be used create a reusable TextBox in your UI:

public class ReusableTextBox extends TextBox {
    //instance variables
    ...

    //constructors
    ...

    @Override
    public Result handleKeyStroke(KeyStroke keyStroke) {
        if (keyStroke.getKeyType() == KeyType.Enter){
            String userInput = getText();
            setText("");
            takeFocus();
            
            //do stuff with userInput and instance variables

            return Result.HANDLED;
        }
        return super.handleKeyStroke(keyStroke);
    }
}

The main downside to this approach is that you would have to implement all the necessary calls to the TextBox constructors yourself:

public ReusableTextBox(/*vals for instance variables,*/
                       String initialContent, TerminalSize preferredSize, Style style){
    super(initialContent, preferredSize, style);
    //init instance variables
}

//and so on for the multiple constructors that take
//various combinations of a String, TerminalSize, or Style

This is somewhat tedious, but you can probably limit yourself to just implementing the constructors you'll actually use.

Andrew
  • 61
  • 7