Reputation: 31
I need to develop a Java application with a GUI, which represents an ATM machine. For that, I must read the Account Number and PIN from the "keypad" (9 buttons). I must read each action of each button pressed (the action listener return the value of the button), and concatenate his number to a string that when the button "ok" is pressed it should return the int (Integer.parseInt()
). My problem is how can i "wait\stop\freeze" my program until had introduced the numbers and pressed "ok"?
I'm sorry if this question was a bit confusing
Thanks for your help ;)
P.S I have a class for each parte of the ATM machine. EG:Keypad , Screen, ATM..etc.
P.S.S If you wish to see some code please tell ;)
Upvotes: 2
Views: 15069
Reputation: 44240
The component that contains the keypad components and "OK" button, should register itself as an ActionListener
to all of them. In order to differentiate between the source components, use the getSource()
method of the EventObject
. Once you've figured out which component generated the event, either add the number to the set, or validate the entered PIN.
The following code snippet attempts to validate the length of an entered PIN number:
Example -
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.ParseException;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.text.MaskFormatter;
final class ATMDemo extends JFrame implements ActionListener{
private static final long serialVersionUID = -8099290319139531183L;
private final JFormattedTextField textField;
private final JPanel layerOne;
private final JPanel layerTwo;
private final JPanel layerThree;
private final JPanel layerFour;
private final JPanel layerFive;
private final JPanel layerSix;
private final JButton one;
private final JButton two;
private final JButton three;
private final JButton four;
private final JButton five;
private final JButton six;
private final JButton seven;
private final JButton eight;
private final JButton nine;
private final JButton zero;
private final JButton okButton;
private final JButton clearButton;
private ATMDemo() throws ParseException{
super("ATM Demo");
getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));
setDefaultCloseOperation(EXIT_ON_CLOSE);
layerOne = new JPanel();
layerTwo = new JPanel();
layerThree = new JPanel();
layerFour = new JPanel();
layerFive = new JPanel();
layerSix = new JPanel();
// Add layer one
textField = new JFormattedTextField(new MaskFormatter("*********"));
textField.setEditable(false);
textField.setColumns(7);
layerOne.add(textField);
// Add layer two
one = new JButton(String.valueOf(1));
two = new JButton(String.valueOf(2));
three = new JButton(String.valueOf(3));
layerTwo.add(one);
layerTwo.add(two);
layerTwo.add(three);
// Add layer three
four = new JButton(String.valueOf(4));
five = new JButton(String.valueOf(5));
six = new JButton(String.valueOf(6));
layerThree.add(four);
layerThree.add(five);
layerThree.add(six);
// Add layer four
seven = new JButton(String.valueOf(7));
eight = new JButton(String.valueOf(8));
nine = new JButton(String.valueOf(9));
layerFour.add(seven);
layerFour.add(eight);
layerFour.add(nine);
// Add layer five
zero = new JButton(String.valueOf(0));
layerFive.add(zero);
// Add layer six
okButton = new JButton("OK");
clearButton = new JButton("Clear");
layerSix.add(okButton);
layerSix.add(clearButton);
}
@Override
public final void actionPerformed(final ActionEvent e) {
final JButton source = (JButton)e.getSource();
if(source.equals(okButton)){
if(textField.getValue() != null && textField.getValue().toString().length() != 9){
JOptionPane.showMessageDialog(this, "Invalid PIN length - must be 9 digits long.", "Error", JOptionPane.ERROR_MESSAGE);
}
else{
JOptionPane.showMessageDialog(this, "Valid PIN length.", "Valid", JOptionPane.INFORMATION_MESSAGE);
}
clearButton.doClick();
}
else if(source.equals(clearButton)){
textField.setValue(null);
}
else{
final StringBuilder sb = new StringBuilder();
if(textField.getValue() != null){
for(char c: textField.getValue().toString().toCharArray()){
sb.append(c);
}
}
if(sb.length() != 9){
sb.append(source.getText());
textField.setValue(sb);
}
}
}
static final ATMDemo newInstance() throws ParseException{
final ATMDemo demo = new ATMDemo();
demo.one.addActionListener(demo);
demo.two.addActionListener(demo);
demo.three.addActionListener(demo);
demo.four.addActionListener(demo);
demo.five.addActionListener(demo);
demo.six.addActionListener(demo);
demo.seven.addActionListener(demo);
demo.eight.addActionListener(demo);
demo.nine.addActionListener(demo);
demo.zero.addActionListener(demo);
demo.okButton.addActionListener(demo);
demo.clearButton.addActionListener(demo);
demo.add(demo.layerOne);
demo.add(demo.layerTwo);
demo.add(demo.layerThree);
demo.add(demo.layerFour);
demo.add(demo.layerFive);
demo.add(demo.layerSix);
demo.setSize(225, 250);
demo.setLocationRelativeTo(null);
return demo;
}
public static final void main(final String[] args) {
SwingUtilities.invokeLater(new Runnable(){
@Override
public void run() {
try {
ATMDemo.newInstance().setVisible(true);
} catch (ParseException e) {
e.printStackTrace();
}
}
});
}
}
a) Invalid PIN length
b) Valid PIN length
Upvotes: 6
Reputation: 285405
You don't want to "freeze" your program. Instead you want to code it so that the listener that responds to the press of the OK button, will only do its action if the number buttons have been pressed previously. This will require that you give the class a variable that holds the results of the last xxx button presses (an array or list could work for this or even a simple String), and then in your ok button's listener, have an if block that checks this variable and if OK, performs its magic.
For example you could have String called pinInput and have it = "" or the empty String (or better, a StringBuilder -- but this is not totally necessary for your simple program). In each number button listener, you concatenate the String representing the number pressed onto the pinInput String. In the OK button's listener you check to see if the pinInput's length is more than the minimum required characters long, and if so, take the last x characters from the String and test if they match the PIN.
Edit:
You state:
The ATM class will be the "main" of the program, and it will call an methode readInt() of class Keypad. it should be here that i get the number that the user introduced.
You can allow the main class to add a listener to any other class if need be, so that it gets notified if a button is pressed.
No matter how you look at this, you'll need to use listeners so that your program responds to events (is "event-driven"). That's how Java Swing GUI's work.
Edit 2
For example here's code where the JFrame holds a JPanel that has JButtons on it, and the JFrame only responds if the buttons on the JPanel are pushed in a certain order -- A, then B, then OK:
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class AnExample {
private static void createAndShowGui() {
AnExample mainPanel = new AnExample();
JFrame frame = new AnExMain();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
class AnExMain extends JFrame {
private JTextField field = new JTextField(
"Press A, then B, then OK, in that order", 20);
private Control control = new Control(this);
public AnExMain() {
add(field, BorderLayout.PAGE_START);
add(new InnerPanel(control), BorderLayout.CENTER);
}
public void fieldSetText(String text) {
field.setText(text);
}
}
class Control {
private AnExMain anExMain;
private String data = "";
public Control(AnExMain anExMain) {
this.anExMain = anExMain;
}
public void btnPressed(String actionCommand) {
anExMain.fieldSetText("");
if (actionCommand.equals("OK")) {
if (data.equals("AB")) {
anExMain.fieldSetText("Buttons pressed in proper order!");
}
data = "";
} else {
data += actionCommand;
if (data.length() > 2) {
data = data.substring(data.length() - 2);
}
}
}
}
class InnerPanel extends JPanel {
public InnerPanel(final Control control) {
JButton btnA = new JButton("A");
JButton btnB = new JButton("B");
JButton btnOK = new JButton("OK");
add(btnA);
add(btnB);
add(btnOK);
ActionListener listener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
control.btnPressed(e.getActionCommand());
}
};
btnA.addActionListener(listener);
btnB.addActionListener(listener);
btnOK.addActionListener(listener);
}
}
Upvotes: 2
Reputation: 168815
Perhaps you are after something like a modal dialog. E.G.
String pinString = JOptionPane.showInputDialog(parent, "PIN");
That will 'freeze' the main GUI until dismissed.
Check the return value. If it is null
, the user cancelled the dialog.
Upvotes: 2
Reputation: 5133
JFrame
.ActionListener
class for your buttons. In the constructor, put the text that the button ActionListener will add if its button is clicked.ActionListener
to each one. For JButton
1, make the ActionListener add "1". For JButton
2, make it add "2". Etc.....Integer.parseInt()
pinString and check the parsed value with the real PIN and do whatever you want to do if they match or they don't match.Upvotes: 3
Reputation: 109547
It would help to look at other code; java calculator tutorials are many. In principle you can have your OK button disabled (setEnabled(false)
) and on 4 keys added to a global String: setEnabled(pinCode.length() == 4)
.
Upvotes: 2