Reputation: 2318
I have an array of JButtons which form a keypad interface. After six numbers are entered I want to disable the keypad so that no further numbers can be entered by the user.
I have written the code and the buttons do disable until the mouse hovers above any of them, then the buttons seem to re-enable themselves and run actionEvents added to them.
The full code is available here.
Possible things that I think are wrong.
button.setEnabled(false);
buildGUI();
correctly, I only did this anyway so that the inner class could access them.gridLayout
as disabling the buttons seems to work for my services
JPanel buttons.Upvotes: 0
Views: 794
Reputation: 29680
Examining the class files was helpful! The problem is in the Driver class:
the buildGUI()
method is being called 2 times: once in the constructor of CashMachine and second in the main
method after calling the constructor.
public static void main(String args[])
{
CashMachine cashmachine = new CashMachine();
cashmachine.buildGUI();
}
This way you end up with the double number of buttons, that is, a pair of buttons at each position. But only one of each is being disabled.
Just remove the call to buildGUI
from main
(or from the constructor).
(I would change buildGUI
to private as it should not be called from outside the class...)
Upvotes: 1
Reputation: 205775
One possible source of confusion in your program is mixing number keys with control keys, Clear
and Enter
. Consider handling number keys separately with a single listener, as suggested in the NumberButton
class shown below. Then you can handle the Clear
and Enter
buttons as desired. Also, using a List<NumberButton>
makes the enable and disable loops easier.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
public class KeyPadPanel extends JPanel implements ActionListener {
private static final int MAX = 6;
private final List<NumberButton> numbers = new ArrayList<NumberButton>();
private final JTextArea text = new JTextArea(1, MAX);
private final JButton clear = new JButton("Clear");
private final JButton enter = new JButton("Enter");
public KeyPadPanel() {
super(new BorderLayout());
JPanel display = new JPanel();
text.setEditable(false);
display.add(text);
this.add(display, BorderLayout.NORTH);
JPanel pad = new JPanel(new GridLayout(4, 4));
for (int i = 0; i < 10; i++) {
NumberButton n = new NumberButton(i);
numbers.add(n);
if (i > 0) {
pad.add(n);
}
}
pad.add(clear);
pad.add(numbers.get(0));
pad.add(enter);
clear.addActionListener(this);
enter.addActionListener(this);
this.add(pad, BorderLayout.CENTER);
}
@Override
public void actionPerformed(ActionEvent e) {
text.setText("");
enableButtons();
}
private void enableButtons() {
for (NumberButton n : numbers) {
n.setEnabled(true);
}
}
private void disableButtons() {
for (NumberButton n : numbers) {
n.setEnabled(false);
}
}
private class NumberButton extends JButton implements ActionListener {
public NumberButton(int number) {
super(String.valueOf(number));
this.addActionListener(this);
}
@Override
public void actionPerformed(ActionEvent e) {
NumberButton b = (NumberButton) e.getSource();
if (text.getText().length() < MAX) {
text.append(b.getText());
}
if (text.getText().length() == MAX) {
disableButtons();
}
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new KeyPadPanel());
f.pack();
f.setVisible(true);
}
});
}
}
Upvotes: 1
Reputation: 5099
The problem lies in how you instantiated your Frame (CashMachine
), not (directly) with its implementation.
You are calling buildGUI
twice, one in the object's constructor, and then in the Driver
class that instantiates the object. As a result, you are creating (and laying out) two sets of buttons.
When the buttons of the first set were eventually disabled, your mousing activity was revealing the second set of buttons. And a flaw in your ActionListener implementation can cause inputCount
to take on values greater than 6, so buttons in the second set were not eventually disabled like those from the first set.
buildGUI
should be private; it should be called in the CashMachine constructor, and not by your Driver
class.
Conversely, in my opinion, CashMachine.setVisible
should be called by the Driver
class, and not by the CashMachine
constructor.
Upvotes: 3