I am working on a java swing project
that looks like a Terminal (but with less functionality).
The GUI contains a jTextArea
to display output and a jTextField
for user input.
Here is an application of the my GUI to perform a simple task.
- Ask the user to enter a number.
- If successful, ask the user to enter a smaller
- If successful, prompt out the text "done!".
Is there a better way to do this other than state machine?
Here is the code:
package com.TerminalPanelGUI;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class TerminalPanel extends javax.swing.JPanel
{
private int state;
/**
* Creates a new Terminal Panel
*/
public TerminalPanel()
{
state = 0;
initComponents();
textArea.setText("Enter a number: \n");
textField.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent ae)
{
System.out.println("In action performed: state is " + state);
switch(state)
{
case 0:
State0();
break;
case 1:
State1();
break;
}
}
});
}
private int dummy;
private void State0()
{
try
{
dummy = Integer.parseInt(textField.getText());
state = 1;
//prompt for next state
textArea.append("Enter a smaller number: \n");
}
catch(NumberFormatException e)
{
textArea.append("Invalid entry. Try again \n");
state = 0;
}
}
private void State1()
{
try
{
if(Integer.parseInt(textField.getText()) < dummy)
{
state = 2;
//prompt for next state
textArea.append("done!");
}
else
{
state = 1;
//prompt for next state
textArea.append("Enter a smaller number: \n");
}
}
catch(NumberFormatException e)
{
textArea.append("Invalid entry. Try again \n");
}
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
scrollPane = new javax.swing.JScrollPane();
textArea = new javax.swing.JTextArea();
textField = new javax.swing.JTextField();
setLayout(new org.netbeans.lib.awtextra.AbsoluteLayout());
textArea.setEditable(false);
textArea.setColumns(20);
textArea.setRows(5);
scrollPane.setViewportView(textArea);
add(scrollPane, new org.netbeans.lib.awtextra.AbsoluteConstraints(0, 0, 400, 250));
add(textField, new org.netbeans.lib.awtextra.AbsoluteConstraints(0, 270, 400, 30));
}// </editor-fold>
// Variables declaration - do not modify
private javax.swing.JScrollPane scrollPane;
protected javax.swing.JTextArea textArea;
protected javax.swing.JTextField textField;
// End of variables declaration
}
1 Answer 1
Maybe something like this? Note: may add textField as a member of State0 and State1
public interface State
{
boolean hasNext();
State next();
}
public final class State0
implements State
{
private boolean okToContinue = false;
private int number;
@Override
public boolean hasNext()
{
try {
textArea.append("Enter a number");
number = Integer.parseInt(textField.getText());
okToContinue = true;
} catch (NumberFormatException ignored) {
textArea.append("Input is not a number");
}
return true;
}
@Override
public State next()
{
return okToContinue ? new State1(number) : this;
}
}
The State1 implementation is then obvious. In the main loop you can just do:
State state = new State0();
while (state.hasNext())
state = state.next();