I'm building a simple program in Java which gets a balance (mine is set to $8000). I want to deposit money into that so I have a UI with 0-9 buttons, a textarea and a deposit button, so if the user wanted to deposit $100 he would press 1 once then 0 twice. All that works and it deposits for the first time, but the second time it deposits the double amount of money. If I press my deposit button 10 times and select $1 then press enter it deposits $10. I think the structure of my btn action listener might be wrong.
Any ideas?
Code:
btnDeposit.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
label1.setText("Deposit: How much would you like to deposit?");
btnWithdraw.setEnabled(false);
btnBalance.setEnabled(false);
btnEnter.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
//convert text area into double
double depositNumber = Double.parseDouble(ta.getText());
sav.deposit(depositNumber);
btnWithdraw.setEnabled(true);
btnBalance.setEnabled(true);
}
});
}
});
My deposit function is:
public void deposit(double depositAmount) {
balance += depositAmount;
System.out.println("Your updated balance is: " + balance);
}
I also noticed that it doesn't go back to where it started, if I keep clicking on Enter it keeps adding and adding...
Button that clear my text area:
btnClear.addActionListener(new new ActionListener(){
#Override
public void actionPerformed(ActionEvent ae) {
ta.setText("");
}
});
The problem is called out in the comment section. You are declaring multiple listeners which are calling the respective deposit() or withdraw() method every time you perform an action.
To avoid this. You can set one listener class to all of your buttons like this.
Create an inner class
private class MySpecialListener implements ActionListener{
#Override
public void actionPerformed(ActionEvent ae) {
if(e.getSource == btnDesposit) // do stuff and so on
}
}
and add the listener like this
MySpecialListener myListener = new MySpecialListener();
btnDeposit.addActionListener(myListener);
The above requires you to re-write your code, but it has a better structure then your current one.
To fix your current problem you can remove the last listener like this:
for(ActionListener al : btnEnter.getActionListeners())
btnEnter.removeActionListener(al)
btnEnter.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
//convert text area into double
double depositNumber = Double.parseDouble(ta.getText());
sav.deposit(depositNumber);
btnWithdraw.setEnabled(true);
btnBalance.setEnabled(true);
}
});
Related
I have 3 TextFields. One is a totalTF the other is a tenderedTF and the last is a changeTF. I am wondering how to go about taking the total price in the totalTF and allowing the user to enter in the amount they give to the cashier into the tenderedTF, then it should work out the change once the pay button is chosen and display in the changeTF. Here is my code so far. Im trying to do the math then set the changeTF. Any help would be greatly appreciated thanks.
JButton payButton = new JButton("Pay");
payButton.setBounds(970, 569, 209, 51);
contentPane.add(payButton);
// Calculate Change
changeTF.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
if(e.getSource() == payButton)
{
double change = Double.valueOf(totalTF.getText()) - Double.valueOf(tenderedTF.getText());
changeTF.setText(String.valueOf(change));
}
}
});
tenderedTF.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
if(e.getSource() == payButton)
{
double change = Double.valueOf(totalTF.getText()) - Double.valueOf(tenderedTF.getText());
changeTF.setText(String.valueOf(change));
}
}
});
You want to execute code when user clicks on payButton, so I think you should add the listener on the payButton:
payButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
double change = Double.valueOf(totalTF.getText()) - Double.valueOf(tenderedTF.getText());
changeTF.setText(String.valueOf(change));
}
});
I think the listeners you added to textfields can't work because e.getSource() returns the textfield that originated the event, it can't be the payButton.
Edit: New revision to include the question posted in comment:
payButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
double change = Double.valueOf(tenderedTF.getText()) - Double.valueOf(totalTF.getText());
if(change<0){
changeTF.setText(String.valueOf(-change) + " missing");
} else {
changeTF.setText(String.valueOf(change));
}
}
});
Honestly I did not compile and test this code but I hope it gives you the idea: check 'change' and provide different messages according to the positive or negative value.
This is a very basic approach, you might want to think of something more sophisticated.
Please note I chenged the computation for the value of change because this new one sounds more in line with the description you gave according to field names. Please double check.
Hope it helps.
Good luck.
The problem is that when the button is clicked and enters the start game method, the program does not wait for the action listener that is included in the question methods. Instead it skips to the last method. Thanks.
//Setting Main Layout
Game.setLayout(new BorderLayout());
Game.add(NorthName, NORTH);
Game.add(SouthScore, SOUTH);
Game.add(Center, CENTER);
//Setting NorthName Layout
NorthName.setLayout(new GridLayout(0,2,2,0));
NorthName.add(name);
NorthName.add(getName);
//Setting SouthScore Layout
SouthScore.setLayout(new FlowLayout());
SouthScore.add(scoreL);
scoreL.setText("Score: " + String.valueOf(scoreN) + "/10");
//Setting Center
Center.setLayout(new GridLayout(4,3,0,0));
Center.add(intro);
Center.add(question);
Center.add(True);
Center.add(False);
Center.add(status);
Center.add(answer);
True.setText("Start");
False.setText("Exit");
intro.setText("");
question.setText("");
status.setText("");
answer.setText("");
True.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
intro.setText("Hello " + getName.getText());
True.setText("True");
False.setText("False");
status.setText("");
answer.setText("");
startGame();
}
});
False.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
intro.setText("Hello guest");
True.setText("True");
False.setText("False");
status.setText("Well... ");
answer.setText("That's too bad. ;)");
startGame();
}
});
}
start game methods
void startGame(){
scoreN = 0;
setQuestionOne();
setQuestionTwo();
setQuestionThree();
setQuestionFour();
setQuestionFive();
setFinalScore();
}
This is what is in the set question methods is the same through out each one.
void setQuestionOne(){
question.setText("i'Robot is about Robots.");
True.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
status.setText("Correct! +3");
answer.setText("This Movie is about robots!");
scoreN = scoreN + 3;
scoreL.setText("Score: " + String.valueOf(scoreN) + "/10");
}
});
False.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
status.setText("Incorrect! +0");
answer.setText("This Movie is about robots!");
scoreN = scoreN + 0;
}
});
}
Use a JOptionPane. You can display each question separately in a JOptionPane. The dialog will only close when the user responds to the dialog.
Read the section from the Swing tutorial on How to Make Dialogs for working examples.
Otherwise you need to redesign your form. That is you would display a single question. Then in the ActionListener for the first question, you would display the second question and so on. In the ActionListener for the second question you display the third question.
Or in your ActionListener you would need to invoke a "Next Question" method. So in this case you would use an ArrayList to hold each question. Then every time a question is answered, you move to the next question in the ArrayList. This is the better approach because you can easily change the number of questions you want to ask. You should never really hard code methods to ask a different question.
Also, variable names should NOT start with an upper case character. Some of you variable names are correct, others are not. Be consistent!
I have two Textfields that can be input by user and will be used for calculation later (Number only), lets say InputX and InputY. And two radio button, Rad1 and Rad2.
When user Choose Rad1, Both TextFiled are Input-able by User and Stored to memory/variable when user input in it. But when user choose Rad2, only InputX is available and InputY is InputY.setText("InputX only"). If User choose the Rad1 back, i want to restore the value that user input to the InputY previously, not showing "InputX Only".
So, My Question is: How to get the previous value from userinput when user choose the Rad1 back, since its has been overridden by Rad2 InputY.setText("InputX Only") ?
Please create a full code example with all possible/alternative code, i'm new in java.
Note: Im using Netbeans v8.0.2 and create form using built in form builder/designer
public class InputValidator extends javax.swing.JFrame {
private static final String INPUT_X_ONLY = "InputX Only";
private String temp = "";
public InputValidator() {
initComponents();
jRadioButton1.setSelected(true);
buttonGroup1.add(jRadioButton1);
buttonGroup1.add(jRadioButton2);
jRadioButton1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
jTextField2.setEditable(true);
jTextField2.setText(temp);
}
});
jRadioButton2.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
jTextField2.setEditable(false);
temp = jTextField2.getText();
jTextField2.setText(INPUT_X_ONLY);
}
});
}
The question is poorly worded, but I'll try to explain. I've created a vending machine where a window pops up and asks user to enter money. They then move to the main machine window and it displays the number they entered as the amount of money they have. I have a button, 'Add Money' that is supposed to add money to that current amount, but i'm not sure how to do that.
For example, a user enters that they have 2 dollars, then hits the enter key which takes them to the main machine interface that states they have 2 dollars.. The user hits the 'add money' button and types 3, denoting that they have 3 more dollars. That should mean they have 5 dollars, and will be denoted on the main interface that they have 5 dollars.
Code for the money input...
public void actionPerformed(ActionEvent arg0) {
double moneyInput;
String text = mInput.getText();
moneyInput = Double.parseDouble (text);
VendingMachineInterface frame;
try {
frame = new VendingMachineInterface(vendingMachineName, moneyInput);
frame.setVisible(true);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
This is one way to do what you want, but since you did not provide an MCVE this might not be what you were looking for.
public class VendingMachine extends JFrame {
static int amount = 0;
VendingMachine() {
JButton add = new JButton("Add amount");
JTextField moneyInput = new JTextField(8);
JLabel currentAmount = new JLabel("Current amount:");
JLabel amountLabel = new JLabel(String.valueOf(amount));
setLayout(new FlowLayout());
add(currentAmount);
add(amountLabel);
add(moneyInput);
add(add);
add.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
String addAmountString = moneyInput.getText();
int addAmount = 0;
try {
addAmount = Integer.parseInt(addAmountString);
} catch (NumberFormatException exp) {
System.out.println("Not a number, amount to add will be 0.");
}
amount += addAmount;
moneyInput.setText("");
amountLabel.setText(String.valueOf(amount));
}
});
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
pack();
setVisible(true);
}
public static void main(String[] args) {
String initialString = JOptionPane.showInputDialog("Enter initial $");
try {
amount = Integer.parseInt(initialString);
} catch (NumberFormatException e) {
System.out.println("Not a number, initial amount will be 0.");
}
new VendingMachine();
}
}
Notes:
You can use an InputVerifier for the text fields instead of checking the value after it is entered.
You can use the input dialog that I used at the beginning each time the button is pressed instead of having the text field in the main window.
I don't know if this is the best way to accomplish your task, but I've used it before in a similar type of application.
Basically, inside the JFrame I had a JPanel which existed only to switch between other panels using the add() and remove() methods.
I created a ManagerPanel class, which has the following method:
public void switchPanel(JPanel removePanel, JPanel addPanel) {
this.remove(removePanel);
this.add(addPanel);
validate();
repaint();
}
To switch panels, I used the following inside an action event:
((ManagerPanel)this.getParent()).switchPanel(currentPanel.this, newPanel);
Like I said, there might be a fancier solution out there, but this was easy and worked for me.
Here's the thing...
I have 2 GUI programs.
A Menu Program,which is basically a frame with buttons of food items,the buttons when clicked
opens this other program,an Input Quantity Program,which is a frame with a text field,buttons for numbers,buttons for Cancel and Confirm. The quantity that is confirmed by the user will be accessed by the menu program from the Input Quantity Program to be stored in a vector so that every time a user wants to order other food items he will just click another button and repeat the process.
Now I've coded the most part and got everything working except one thing,the value returned by the Input Quantity Program has this delay thing.
This is what I do step by step:
1)Click a food item in Menu,it opens the Input Quantity window.
2)I input the number I want,it displayed in the text box correctly.
3)I pressed confirm which will do 3 things,first it stores the value of the text field to a variable,second it will call the dispose() method and third a print statement showing the value of the variable(for testing purposes).
4)The menu program then checks if the user has already pressed the Confirm button in the Input program,if true it shall call a method in the Input program called getQuantity() which returns the value of the variable 'quantity' and store it in the vector.
5)After which executes another print statement to check if the passed value is correct and then calls the method print() to show the ordered item name and it's recorded quantity.
Here are the screenshots of the GUI and the code will be below it.
ActionPerformed method of the CONFIRM BUTTON in the Input Quantity Program:
private void ConfirmButtonActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
confirmed = true;
q= textField.getText().toString();
quantity =Integer.parseInt(q) ;
System.out.println("getQTY method inside Input Quantity Interface:" +getQuantity());
System.out.println("Quantity from confirmButton in Input Quantity Interface actionPerformed: "+quantity);
//getQuantity();
}
ACTION LISTENER CLASS of the MENU ITEM BUTTONS in MENU PROGRAM which does step 2 above:
class f implements ActionListener {
#Override
public void actionPerformed(ActionEvent e)
{
inputGUI.setVisible(true);
int q =0;
q=inputGUI.getQuantity(); //call method to get value from Input Program
System.out.println("Quantity inside Menu actionperformed from AskQuantity interface: "+q);
orderedQuantity.add(q); //int vector
textArea.append("\n"+e.getActionCommand()+"\t"+ q);
orderedItems.add(e.getActionCommand()); //String vector
print();
/*
System.out.println("Enter QTY: ");
int qty = in.nextInt();
orderedQuantity.add(qty);
print();*/
}
Here are screenshots of the print statements in the console:
Here I first ordered Pumpkin Soup,I entered a quantity of 1
Here I ordered seafood marinara and entered a quantity of 2
Here I ordered the last item,pan fried salmon and entered a quantity of 3
As you can see the first recorded quantity is 0 for the first item I ordered then when I added another item,the quantity of the first item gets recorded but the 2nd item's quantity is not recorded..same goes after the third item... and the quantity of the 3rd item is not recorded even if the program terminates :(
How can I solve this problem?
I think I see your problem, and in fact it stems directly from you're not using a modal dialog to get your input. You are querying the inputGUI before the user has had a chance to interact with it. Hang on while I show you a small example of what I mean...
Edit
Here's my example code that has a modal JDialog and a JFrame, both acting as a dialog to a main JFrame, and both using the very same JPanel for input. The difference being the modal JDialog will freeze the code of the main JFrame at the point that it has been made visible and won't resume until it has been made invisible -- thus the code will wait for the user to deal with the dialog before it progresses, and therein holds all the difference.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class DialogExample {
private static void createAndShowGui() {
JFrame frame = new JFrame("Dialog Example");
MainPanel mainPanel = new MainPanel(frame);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
class MainPanel extends JPanel {
private InputPanel inputPanel = new InputPanel();
private JTextField responseField = new JTextField(10);
private JDialog inputDialog;
private JFrame inputFrame;
public MainPanel(final JFrame mainJFrame) {
responseField.setEditable(false);
responseField.setFocusable(false);
add(responseField);
add(new JButton(new AbstractAction("Open Input Modal Dialog") {
#Override
public void actionPerformed(ActionEvent e) {
if (inputDialog == null) {
inputDialog = new JDialog(mainJFrame, "Input Dialog", true);
}
inputDialog.getContentPane().add(inputPanel);
inputDialog.pack();
inputDialog.setLocationRelativeTo(mainJFrame);
inputDialog.setVisible(true);
// all code is now suspended at this point until the dialog has been
// made invisible
if (inputPanel.isConfirmed()) {
responseField.setText(inputPanel.getInputFieldText());
inputPanel.setConfirmed(false);
}
}
}));
add(new JButton(new AbstractAction("Open Input JFrame") {
#Override
public void actionPerformed(ActionEvent e) {
if (inputFrame == null) {
inputFrame = new JFrame("Input Frame");
}
inputFrame.getContentPane().add(inputPanel);
inputFrame.pack();
inputFrame.setLocationRelativeTo(mainJFrame);
inputFrame.setVisible(true);
// all code continues whether or not the inputFrame has been
// dealt with or not.
if (inputPanel.isConfirmed()) {
responseField.setText(inputPanel.getInputFieldText());
inputPanel.setConfirmed(false);
}
}
}));
}
}
class InputPanel extends JPanel {
private JTextField inputField = new JTextField(10);
private JButton confirmBtn = new JButton("Confirm");
private JButton cancelBtn = new JButton("Cancel");
private boolean confirmed = false;
public InputPanel() {
add(inputField);
add(confirmBtn);
add(cancelBtn);
confirmBtn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
confirmed = true;
Window win = SwingUtilities.getWindowAncestor(InputPanel.this);
win.setVisible(false);
}
});
cancelBtn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
confirmed = false;
Window win = SwingUtilities.getWindowAncestor(InputPanel.this);
win.setVisible(false);
}
});
}
public boolean isConfirmed() {
return confirmed;
}
public void setConfirmed(boolean confirmed) {
this.confirmed = confirmed;
}
public String getInputFieldText() {
return inputField.getText();
}
}
So solution: use a modal JDialog.
Suppose i am having two GUI frames f1 and f2. Now by clicking a button on f1 i want to invoke frame f2 and also sending some data from f1(frame class) to f2(frame class).
One possible way is to declare a constructor in f2 which takes the same data as parameters which i wanted to send to it from f1.Now in frame f1's coding just include these statements:
f1.setVisible(false);//f1 gets invisible
f2 newFrame=new f2(uname,pass);//uname and pass have been takenfrom f1's text fields
f2.setVisible(true);
I think this will clear up your problem.