user1118437
user1118437

Reputation: 31

Java multiple Button action

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

Answers (5)

mre
mre

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();
                }
            }
        });
    }
}

enter image description here

a) Invalid PIN length

enter image description here

b) Valid PIN length

enter image description here

Upvotes: 6

Hovercraft Full Of Eels
Hovercraft Full Of Eels

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

Andrew Thompson
Andrew Thompson

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

eboix
eboix

Reputation: 5133

  1. Make a JFrame.
  2. Make an instance variable called pinString. Initialize it to "".
  3. Make a 'JPanel'.
  4. Define an ActionListener class for your buttons. In the constructor, put the text that the button ActionListener will add if its button is clicked.
  5. Make 9 buttons. Add the ActionListener to each one. For JButton 1, make the ActionListener add "1". For JButton 2, make it add "2". Etc.....
  6. Add the buttons to the JPanel.
  7. Make another JButton, the OK button.
  8. Have its action listener 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.
  9. Add the button to the panel.
  10. Set the Frame's content pane to be the panel.
  11. Show/Pack the Frame. It should work.

Upvotes: 3

Joop Eggen
Joop Eggen

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

Related Questions