JavaFX Action Event - Pull from Array - java

Working on a school project, I am trying to get the action of clicking a button pull the selected index of a Combo Box string array, and associated that index with an int array so that a final price can be computed. Doesn't seem to work the price just remains at zero when button is pressed.
private final String[] deckArray = {"The Master
Thrasher ", "The Dictator", "The Street King"};
private final String[] trucksArray = {"7.75-inch
axle", "8-inch axle", "8.5-inch axle"};
private final String[] wheelsArray = {"51mm", "55mm",
"58mm", "61mm"};
private final int[] deckPrice = {60,45,50};
private final int[] trucksPrice = {35,40,45};
private final int[] wheelsPrice = {20,22,24,28};
comboDecks = new ComboBox();
comboDecks.getItems().addAll(deckArray);
comboTrucks = new ComboBox();
comboTrucks.getItems().addAll(trucksArray);
comboWheels = new ComboBox();
comboWheels.getItems().addAll(wheelsArray);
btnCalc = new Button("Calculate Total");
lblFinalPrice = new Label("Final Price:");
txtSubtotal = new Text("Subtotal: " + finalSubPrice);
txtTax = new Text("Tax:" + finalTaxPrice);
txtFinalPrice = new Text("Final Price: " +
finalTotalPrice);
EventHandler<ActionEvent> calcHandler = new
EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent actionEvent) {
finalDeckPrice = deckPrice[comboDecks.getSelectionModel().getSelectedIndex()];
finalTruckPrice = trucksPrice[comboTrucks.getSelectionModel().getSelectedIndex()];
finalWheelsPrice = wheelsPrice[comboWheels.getSelectionModel().getSelectedIndex()];
finalSubPrice = finalDeckPrice + finalTruckPrice + finalWheelsPrice;
finalTaxPrice = finalSubPrice * salesTax;
finalTotalPrice = finalSubPrice + finalTaxPrice;
}
};

You made the button, you made the event handler, but you never connected the event handler to the button. Same goes for the calculation and the label, you calculated but did not update the label with the calculated value.
Add the following line to your code after you create the handler.
btnCalc.setOnAction(calcHandler);
And add txtFinalPrice.setText(""+finalTotalPrice); after you finish calculations inside handle() method.
public void handle(ActionEvent actionEvent) {
...
finalTotalPrice = finalSubPrice + finalTaxPrice;
txtFinalPrice.setText("Final Price: " + finalTotalPrice);
}
Explanation (Abstract)
(1) When you create an Event Handler object you just wrote the code you want it to run but it won't run in serial as the code executes top to bottom, since as you said you want it to work when you click the button. So you have to let the Button know that when it gets clicked to execute this code. setOnAction() method takes as parameter an Event Handler object and executes it when some action happens to the Button, the action for the Button is when it gets clicked.
(2) Just by calculating the value, doesn't mean the Label knows that the value got calculated or something. The point where you calculating the price is the point that you have to tell to the Label take this value and use this as your content.
Suggestion
Event handlers, action events etc need a bit of good understanding to use them correctly. The baseline is that all of that work asynchronously and you gotta get at least the idea of it so you can understand the rest (no offense but from the question i believe you need some work on it).

Related

Adding a new button after an event

Writing a program to increment a counter when a +1 button is pressed, then when the counter reaches a certain number, remove the +1 button and replace it with a +2 button and so on. I create both buttons at first but just set btnCount1 to setVisible(false). When the certain number passes, I make btnCount invisible and btnCount1 visible and increment by two from there. When it reaches 10 clicks, the btnCount disappears, but btnCount1 does not appear.
I have tried making an if(arg0.equals(btnCount1)), and incrementing by two from there. I tried putting the add(btnCount1) inside the else if statement to create it after the elseif condition is true.
public class AWTCounter extends Frame implements ActionListener
private Label lblCount;
private TextField tfCount;
private Button btnCount;
private Button btnCount1;
private int count = 0;
public AWTCounter() {
setLayout(new FlowLayout());
lblCount = new Label("Counter");
add(lblCount);
tfCount = new TextField(count + "",10);
tfCount.setEditable(false);
add(tfCount);
btnCount = new Button("Add 1");
btnCount1 = new Button("Add 2");
add(btnCount);
add(btnCount1);
btnCount1.setVisible(false);
btnCount.addActionListener(this);
btnCount1.addActionListener(this);
setTitle("AWT Counter");
setSize(500,500);
}
public static void main(String[]args) {
AWTCounter app = new AWTCounter();
}
public void actionPerformed(ActionEvent arg0) {
if(count <= 10) {
++count; //Increase the counter value
tfCount.setText(count + "");
}else if(count > 10) {
btnCount.setVisible(false);
btnCount1.setVisible(true);
count += 2;
tfCount.setText(count + "");
}
}
The better solution here is to just have one button object and a separate variable for the current increment amount. When you hit the required count, increase the increment amount and change the button's label to the new value.
There are also a few other things you could do better here.
Use String.valueOf() instead of int + "" for String representations of integers if you're not adding words before or after the integer.
Don't add obvious comments for code. (e.g. 'increment variable x', 'set textString to the new value')
Use descriptive names for method parameters and variables.
Use Labels instead of TextFields for text that doesn't need to be editable or selectable like counter displays.
I'd personally change the name of lblCount to something like lblTitle as well, since changing your tfCount to a Label would logically take up that name and lblTitle makes more sense.
Here's a better way to implement actionPerformed:
private int increment = 1;
private Label lblCount;
...
public void actionPerformed(ActionEvent ignore) {
if(count == 10) {
btnCount.setLabel("Add " + (++increment));
}
lblCount.setText(String.valueOf(count += increment));
}

Java determining if which JRadioButton was selected

I know that it is possible in an event driven program in Java to find out what object caused an event (e.g. JRadioButton was selected, therefore a certain action will take place). My question is, if you have 2 JRadioButtons in a buttongroup, both with action listeners added to them, and you keep selecting from one to the other, is it possible to find out what JRadioButton was previously selected? In other words, if I selected another JRadioButton, is it possible to write code that determines which JRadioButton was previously selected before selecting the current JRadioButton?
public class Drinks extends JPanel implements ActionListener{
double drinksPrice = 2.10;
double noDrinks = 0;
static String selectedDrink;
JRadioButton btnPepsi = new JRadioButton("Pepsi"); //add a button to choose different drinks
JRadioButton btnMtDew = new JRadioButton("Mt Dew");
JRadioButton btnDietPepsi= new JRadioButton("Diet Pepsi");
JRadioButton btnCoffee = new JRadioButton("Coffee");
JRadioButton btnTea = new JRadioButton("Tea");
JRadioButton btnNone = new JRadioButton("None");
JLabel lblDrinksHeading = new JLabel("Choose a drink (each drink is $2.10):");
ButtonGroup drinksButtonGroup = new ButtonGroup();
private static final long serialVersionUID = 1L;
public Drinks(){
setLayout(new FlowLayout()); //Using GridLayout
btnPepsi.setActionCommand(btnPepsi.getText()); //set the ActionCommand to getText so I can retrieve the name for the receipt
btnMtDew.setActionCommand(btnMtDew.getText());
btnDietPepsi.setActionCommand(btnDietPepsi.getText());
btnCoffee.setActionCommand(btnCoffee.getText());
btnTea.setActionCommand(btnTea.getText());
btnNone.setActionCommand(btnNone.getText());
drinksButtonGroup.add(btnPepsi);
drinksButtonGroup.add(btnMtDew);
drinksButtonGroup.add(btnDietPepsi);
drinksButtonGroup.add(btnCoffee);
drinksButtonGroup.add(btnTea);
drinksButtonGroup.add(btnNone);
btnNone.setSelected(true); //set default to "none"
btnPepsi.addActionListener(this);
btnMtDew.addActionListener(this);
btnDietPepsi.addActionListener(this);
btnCoffee.addActionListener(this);
btnTea.addActionListener(this);
btnNone.addActionListener(this);
add(lblDrinksHeading);
add(btnPepsi);
add(btnDietPepsi);
add(btnMtDew);
add(btnCoffee);
add(btnTea);
add(btnNone);
repaint();
revalidate();
selectedDrink = drinksButtonGroup.getSelection().getActionCommand();
//add the drink price to totalPrice, it is adding it every time though, even if its none
/*if(drinksButtonGroup.getSelection() == btnNone){
MenuFrame.totalPrice += 0;
}
else{
MenuFrame.totalPrice += drinksPrice;
}
*/
// buttonGroup1.getSelection().getActionCommand()
//String selectedDrink = drinksButtonGroup.getSelection().toString();
//class
}
#Override
public void actionPerformed(ActionEvent e) {
Object source = e.getSource();
if(source == btnNone) {
MenuFrame.totalPrice += 0;
TaxAndGratuityFrame.subtotalTextField.setText("$" + MenuFrame.totalPrice);
TaxAndGratuityFrame.subtotalVariable = MenuFrame.totalPrice;
TaxAndGratuityFrame.taxVariable = TaxAndGratuityFrame.subtotalVariable * TaxAndGratuityFrame.TAX_RATE;
TaxAndGratuityFrame.taxTextField.setText("$" + TaxAndGratuityFrame.taxVariable);
Receipt.receiptTotal.setText("Total: $" + (MenuFrame.totalPrice));
Receipt.receiptsubtotal.setText("Subtotal: " + (TaxAndGratuityFrame.subtotalVariable));
}
else {
MenuFrame.totalPrice += drinksPrice;
TaxAndGratuityFrame.subtotalTextField.setText("$" + MenuFrame.totalPrice);
TaxAndGratuityFrame.subtotalVariable = MenuFrame.totalPrice;
TaxAndGratuityFrame.taxVariable = TaxAndGratuityFrame.subtotalVariable * TaxAndGratuityFrame.TAX_RATE;
TaxAndGratuityFrame.taxTextField.setText("$" + TaxAndGratuityFrame.taxVariable);
Receipt.receiptTotal.setText("Total: $" + (MenuFrame.totalPrice));
Receipt.receiptsubtotal.setText("Subtotal: " + (TaxAndGratuityFrame.subtotalVariable));
}
}
Edit: I'll be more specific. I am creating an "imaginary" restaurant program. In it, I list several drinks that have the same price (e.g. Pepsi: $2.10, Mountain Due: $2.10, etc). These listed drinks are JRadioButtons. Once a customer clicks one of these buttons to "order a drink", $2.10 will be added to a "total" variable. However, a problem occurs when a user wants to change there drink, because if they click a different JRadioButton, $2.10 will still be added to the "total" variable. I want to make it so that they can change there drink without adding $2.10 to the order every time.
I think the problem is at this line:
MenuFrame.totalPrice += drinksPrice;
Because "+=" increments a value by another value instead of simply adding two values.
So every time the user clicks on one of the radio buttons, it will continuously add 2.10 to your total value, whereas if you were you just say:
MenuFrame.totalPrice = MenuFrame.totalPrice + drinksPrice;
It will set your total price equal to the current total price plus the price of drinks, instead of adding 2.10 to the total value every time a button is pressed.
Perhaps I am misunderstanding the question, but I am thinking along the lines of creating a public variable, and then inside the action listeners updating the variable with the radio button that was just selected. When the selected event fires, you can look at the variable to see which radio button had last been selected, do what you want to about it, and then update it with the new radio button.

Codename One: Implementing a calculation for a fluid tracker

I am trying to implement a recurrent addition calculation. This should get the current quantity (from the Quantity textfield) and the saved quantity (total quantity to be saved), outputting the total result below the 'Results' heading. View of tabbed page for calculation.
I have tried the following code, but it contains errors and uses a Dialog to output the result (which is not what I want).
addItem.addComponent(selectItem);
TextField quantity = new TextField("", "Quantity (ml or g)", 4, TextArea.NUMERIC);
addItem.addComponent(quantity);
Button add = new Button("Add");
addItem.addComponent(add);
TextArea results = new TextArea("Results");
addItem.addComponent(results);
//TextArea total = new TextArea("Add Item");
//addItem.addComponent(total);
//--------------------------------------------------------------
add.addActionListener((ActionEvent ev) -> {
Storage s = Storage.getInstance();
Integer addition = 0;
// Read my "Hello World" string back from storage
addition = (Integer)s.readObject("total");
int d = Int.parseInt(quantity.getText());
Integer total = addition + quantity;
// Save the "Hello World" string to storage
s.writeObject("total", total);
Dialog.show("", total, "OK", "Cancel");
});
//--------------------------------------------------------------
return addItem;
I would therefore appreciate any advice and guidance on how this could be implemented in my code.
To present it in a table , you can use easily GridLayout in this way :
Container ctrResultTable = new Container(new GridLayout(1,3));
//Define a new container associated to a gridlayout with 1 row and 1 column
ctrResult.addComponent(new Label(d.toString()));
ctrResult.addComponent(new Label(total.toString()));
ctrResult.addComponent(new Label((total/target*100).toString()));
//Because you use a value inside a function, addItem should be initialized as final
addItem.addComponent(ctrResult);
But i can't do nothing for your code error because i can't see the full code here

How can I make a javafx program that takes a number or two and calls a method from another class with that information?

public ComplexNum add(ComplexNum c){
double addedReal = (this.real + c.real);
double addedImag = (this.imag + c.imag);
System.out.println(addedReal);
return new ComplexNum(addedReal,addedImag);
}
This is one of the simpler methods. I want to make a controller class that lets a user enter the first number, press an addition button, enter the second number, press enter, and then have the string representation of the return value printed to a label. I'm not sure how I can call the right method using the controller. I though that maybe I should have a method that checks for specific text(say "add") from the button pressed and executes the correct method for it but I feel like that's not the right way.
I basically want the first number entered to be treated as the "this" pointer for each of the methods, and any following numbers as the parameter.
You have to set an action listener on the button. Example using JavaFX 8:
Button button = new Button();
button.setText("Button Text");
button.setOnAction((ActionEvent event) -> {
System.out.println("Button Clicked!");
});
For you ENTER input, you need to add an event handler to your node. E.g.:
Scene scene = new Scene(root);
scene.addEventHandler(KeyEvent.KEY_PRESSED, (KeyEvent key) -> {
if(key.getCode().equals(KeyCode.ENTER)) {
System.out.println("ENTER pressed");
}
}
You could do something like this (this obviously is incomplete) hopefully can point you in a direction:
long runningTotal = 0;
Button plusButton = new Button("+");
Button enterButton = new Button("Enter");
TextField tf = new TextField();
Label displayLabel = new Label();
//Setup you UI here
plusButton.setOnAction(event -> {
String stringValue = tx.getText();
long value = Long.parseLong(stringValue);
runningTotal = runningTotal + value;
});
enterButton.setOnAction(event -> {
//if you need to remember your last pressed button, you could have done that also, then perform that action here
displayLabel.setText("" + runningTotal);
});

JTextArea append() method writes twice?

I've run into a little problem.
In my GUI, I have a text area in the center (BorderLayout). Then I have a JList on the West.
When I click on a member of the song titles I have in my list, the text area should display the title, artist, and price of the song.
I have everything working, but the problem is that when I click on a member, the title,artist, and the price is displayed TWICE.
Here is the code for "valueChanged()" and parts of codes relevant.
public void valueChanged(ListSelectionEvent e)
{
Object source = e.getSource();
int index = songList.getSelectedIndex();
Song selection = songCollection[index];
if(source == songList)
{
textArea.append(selection.getTitle() + " " + selection.getArtist() + " " + selection.getPrice() + "\n" );
}
}
private Song songCollection[] = new Song[5];
private String songTitle[] = new String[5];
//Fill song array
songCollection = getSongs();
songTitle = getSongTitle();
//Methods:
public Song[] getSongs()
{
Song[] array = new Song[5];
array[0] = new Song("Summer", "Mozart", 1.50);
array[1] = new Song("Winter", "Mozart", 1.25);
array[2] = new Song("Spring", "Mozart", 2.00);
array[3] = new Song("Baby", "Justin Bieber", 0.50);
array[4] = new Song("Firework", "Katy Perry", 1.00);
return array;
}
public String[] getSongTitle()
{
String[] names = new String[5];
for(int i = 0; i < 5; i++)
names[i] = songCollection[i].getTitle();
return names;
}
I noticed something just now when I was fiddling around with my program again. When I press a member in the list, it is still printed TWICE like before. However, I noticed that it prints once when I press and hold down my mouse, and it prints AGAIN when I let go of it. So if I press my mouse on 1 member, and drag the cursor up/down to other members, they print once, but when I let go of the mouse, it prints the one I ended in one more time.
JTextArea.append() is being called twice from your ListSelectionListener.
The reason can be found in How to Use Lists:
Many list selection events can be generated from a single user action such as a mouse click. The getValueIsAdjusting method returns true if the user is still manipulating the selection. This particular program is interested only in the final result of the user's action, so the valueChanged method does something only if getValueIsAdjusting returns false.
You need to check that the selection in the JList is no longer being manipulated. You can surround the append method with the check:
if (!e.getValueIsAdjusting()) {
textArea.append(...);
}

Categories