Add values when JCheckBox clicked - java

My program contains a label with the caption “Choose a coffee” and four check boxes – Americano, Espresso, Double Espresso and Latte. Note: A JCheckBox array is recommended here)
I need to add event handling code to allow the user to purchase one or more items. The bill amount is displayed in a label after the user has made their selections.
The prices are Americano €3.75, Espresso €4.00, Double Espresso €4.50 and Latte €3.50. An array is suitable here also.
As the user makes a choice a label is displayed showing the bill.
I cant figure out how to add the cost when the check box is selected and remove the cost when it is de selected using the arrays.
Any help appreciated.
This is my code so far:
package Lab4EventHandling;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class Frame3 extends JFrame implements ActionListener {
private Container cPane;
private JLabel tMsg, bMsg;
private JCheckBox americano, espresso, doubleEspresso, latte;
JCheckBox[] boxes = new JCheckBox[]{americano, espresso, doubleEspresso, latte};
private JPanel checkPanel = new JPanel(new GridLayout(0,1));
private Color cl;
private double cost = 0;
private final int WINDOW_WIDTH = 200;
private final int WINDOW_HEIGHT = 200;
private final int x = 550;
private final int y = 400;
public Frame3()
{
cPane = getContentPane();
cl = new Color(150, 150, 250);
cPane.setBackground(cl);
this.setLayout(new BorderLayout(0,1));
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocation(x,y);
this.add(checkPanel, BorderLayout.CENTER);
tMsg = new JLabel("Choose a coffee:" ,SwingConstants.CENTER);
tMsg.setBorder(BorderFactory.createEmptyBorder(4,4,4,4));
this.add(tMsg, BorderLayout.PAGE_START);
americano = new JCheckBox("Americano", false);
checkPanel.add(americano);
americano.addActionListener(this);
espresso = new JCheckBox("Espresso", false);
checkPanel.add(espresso);
espresso.addActionListener(this);
doubleEspresso = new JCheckBox("Double Espresso", false);
checkPanel.add(doubleEspresso);
doubleEspresso.addActionListener(this);
latte = new JCheckBox("Latte", false);
checkPanel.add(latte);
latte.addActionListener(this);
bMsg = new JLabel("Bill is ");
bMsg.setHorizontalAlignment(SwingConstants.CENTER);
bMsg.setBorder(BorderFactory.createEmptyBorder(4,4,4,4));
this.add(bMsg, BorderLayout.SOUTH);
this.setSize(WINDOW_WIDTH, WINDOW_HEIGHT);
this.setVisible(true);
}
public void actionPerformed(ActionEvent e) {
Double[] array = {3.75, 4.00, 4.50, 3.50};
for (JCheckBox box : boxes) {
if(americano.isSelected())
{
cost += 3.75;
String r = String.valueOf(cost);
bMsg.setText(r);
}
if(espresso.isSelected())
{
cost += 4.00;
String r = String.valueOf(cost);
bMsg.setText(r);
}
else if(doubleEspresso.isSelected())
{
cost = 4.50;
String r = String.valueOf(cost);
bMsg.setText(r);
}
else if(latte.isSelected())
{
cost = 3.50;
String r = String.valueOf(cost);
bMsg.setText(r);
}
}
}
public class Frame3Test{
public static void main(String [] args)
{
Frame3 f = new Frame3();
f.setVisible(true);
}
}

Your first problem (which you may or may not have noticed) is your array of JCheckBoxes only contains null elements:
// check boxes are null here
private JCheckBox americano, espresso, doubleEspresso, latte;
// array created with only null elements
JCheckBox[] boxes = new JCheckBox[]{americano, espresso, doubleEspresso, latte};
So you need to create the array after instantiating the actual check boxes.
...
americano = new JCheckBox("Americano", false);
checkPanel.add(americano);
americano.addActionListener(this);
espresso = new JCheckBox("Espresso", false);
checkPanel.add(espresso);
espresso.addActionListener(this);
doubleEspresso = new JCheckBox("Double Espresso", false);
checkPanel.add(doubleEspresso);
doubleEspresso.addActionListener(this);
latte = new JCheckBox("Latte", false);
checkPanel.add(latte);
boxes = new JCheckBox[] {
americano, espresso, doubleEspresso, latte
};
Then the assignment is suggesting to use arrays because you can create another parallel array of prices (which you did). But since you need these prices in parallel you cannot use a for each loop. You need the index. Then you need to recalculate the entire cost every time anything is selected or deselected.
final double[] prices = {
3.75, 4.00, 4.50, 3.50
};
...
double total = 0.0;
for(int i = 0; i < boxes.length; i++) {
if(boxes[i].isSelected()) {
total += prices[i];
}
}
There's two other notes that seem to be outside the scope of the assignment:
You should always make a class for this kind of association.
You should never use double for money. Use BigDecimal or something like it.
Using a class makes logic simpler and not using double makes the calculation not incur error for this decimal addition.
class PricePair {
JCheckBox jCheckBox;
BigDecimal price;
}
BigDecimal total = new BigDecimal("0.00");
for(PricePair option : options) {
if(option.jCheckBox.isSelected()) {
total = total.add(option.price);
}
}

First of all, you're not handling all the checkboxes the same way. For the first two choices, you add the price to the cost:
cost += 3.75;
whereas for the last two choices, you replace the cost:
cost = 4.50;
The first way is the correct way.
Second, there's no reason to have the cost as a field. You should recompute the cost, and it should always start with 0, every time a checkbox selection changes. So cost should be a local variable of the actionPerformed() method.
Third, there's no reason to change the label value before you know the final cost. So the lines
String r = String.valueOf(cost);
bMsg.setText(r);
should only be there once, at the end of the actionPerformed() method, when the final cost is known.
Finally, you want to use it us an array instead of handling each checkbos separately. It's quite easy, you just need to loop over the checkboxes:
double prices = {3.75, 4.00, 4.50, 3.50};
double cost = 0.0;
for (int i = 0; i < boxes.length; i++) {
if (boxes[i].isSelected()) {
double price = prices[i];
cost += price;
}
}
// now display the cost in the label

Although both answers posted here are very helpful I'm adding this one because IMHO arrays are the less Object Oriented thing ever. You can achieve a more robust and OO solution following this hints:
Use
putClientProperty()
method inherited from
JComponent
to hold the prices in the check boxes.
Implement an ActionListener to add/substract the check box price to the total depending on the check box state. Use getClientProperty() method to retrieve the value stored in the check box.
See the example below:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.math.BigDecimal;
import java.math.BigInteger;
import javax.swing.BoxLayout;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Demo {
BigDecimal total = new BigDecimal(BigInteger.ZERO);
private void createAndShowGUI() {
final JLabel totalLabel = new JLabel("Total: ");
ActionListener actionListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JCheckBox checkBox = (JCheckBox)e.getSource();
BigDecimal value = (BigDecimal)checkBox.getClientProperty("price");
total = checkBox.isSelected() ? total.add(value) : total.subtract(value);
StringBuilder sb = new StringBuilder("Total: ").append(total);
totalLabel.setText(sb.toString());
}
};
JCheckBox americano = new JCheckBox("Americano");
americano.addActionListener(actionListener);
americano.putClientProperty("price", new BigDecimal("3.75"));
JCheckBox espresso = new JCheckBox("Espresso");
espresso.addActionListener(actionListener);
espresso.putClientProperty("price", new BigDecimal("4.00"));
JCheckBox doubleEspresso = new JCheckBox("Double Espresso");
doubleEspresso.addActionListener(actionListener);
doubleEspresso.putClientProperty("price", new BigDecimal("4.50"));
JCheckBox latte = new JCheckBox("Latte");
latte.addActionListener(actionListener);
latte.putClientProperty("price", new BigDecimal("3.50"));
JPanel content = new JPanel();
content.setLayout(new BoxLayout(content, BoxLayout.PAGE_AXIS));
content.add(americano);
content.add(espresso);
content.add(doubleEspresso);
content.add(latte);
content.add(totalLabel);
JFrame frame = new JFrame("Demo");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(content);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Demo().createAndShowGUI();
}
});
}
}
This way you can forget about mapping every check box with a value using arrays or maps. If you need to add a new sort of coffee you should simply add 4 lines like this:
JCheckBox newCoffee = new JCheckBox("New Coffee");
newCoffee.addActionListener(actionListener);
newCoffee.putClientProperty("price", new BigDecimal("4.00"));
content.add(newCoffee);

Related

GetChangeGui manual JFrame

I'm trying to write a code for my CS 1 class.
The point of the code is to write a code where you are making change out of a hundred dollar bill out for what ever amount, I need to give back the appropriate bills and coins.
I have to write the JFrame manually
It would be helpful if someone could show me where I'm going wrong in the computation.
/**
*
* #author esamayoa
*/
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class GetChange extends JFrame {
//Declare variables
JButton bCompute, bReset;
JTextField tAmount, tQuarters, tDimes, tNickels, tPennies, tTwenty, tTen, tFive, tOne;
JLabel lAmount, lQuarters, lDimes, lNickels, lPennies, lTwenty, lTen, lFive, lOne;
double amount, diff, totalPaid, quarter, dime, nickel, penny, twenty, ten, five, one;
public GetChange (){
//Set the attributes of the Jframe
setTitle("Eric");
setLocation(500,10);
setSize(450,1000);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setResizable(false);
setVisible(true);
//Create your Gui components
lAmount = new JLabel("Amount");
lQuarters = new JLabel("Quarters:");
lDimes = new JLabel("Dimes:");
lNickels = new JLabel("Nickels:");
lPennies = new JLabel("Pennies:");
lTwenty = new JLabel("Twenties");
lTen = new JLabel("Tens");
lFive = new JLabel("Fives");
lOne = new JLabel("Ones");
tAmount = new JTextField();
tQuarters = new JTextField();
tDimes = new JTextField();
tNickels = new JTextField();
tPennies = new JTextField();
tTwenty = new JTextField();
tTen = new JTextField();
tFive = new JTextField();
tOne = new JTextField();
bReset = new JButton("Reset");
bCompute = new JButton("Compute");
//Add you Gui components to the Jframe
setLayout(new GridLayout(10,2));
add(lAmount);
add(tAmount);
add(lQuarters);
add(tQuarters);
add(lDimes);
add(tDimes);
add(lNickels);
add(tNickels);
add(lPennies);
add(tPennies);
add(lTwenty);
add(tTwenty);
add(lTen);
add(tTen);
add(lFive);
add(tFive);
add(lOne);
add(tOne);
add(bCompute);
add(bReset);
//Updates frame
this.validate();
//Add Action Listeners to buttons
bReset.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
tAmount.setText("");
tQuarters.setText("");
tDimes.setText("");
tNickels.setText("");
tPennies.setText("");
tTwenty.setText("");
tTen.setText("");
tFive.setText("");
tOne.setText("");
tAmount.setText("");
}
});
//Create computation for compute button
bCompute.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
totalPaid = 100;
amount = Double.parseDouble(tAmount.getText());
diff = totalPaid-amount;
twenty = diff/20;
diff = diff%20;
tTwenty.setText(""+ twenty);
ten = diff/10;
diff = diff%10;
tTen.setText(""+ ten);
five = diff/5;
diff = diff%5;
tFive.setText(""+ five);
one = diff/1;
diff = diff%1;
tOne.setText(""+ one);
quarter = diff/.25;
diff = diff%.25;
tQuarters.setText(""+ quarter);
dime = diff/.1;
diff = diff%.1;
tDimes.setText(""+ dime);
nickel = diff/.05;
diff = diff%.05;
tNickels.setText(""+ nickel);
penny = diff/.01;
diff = diff%.01;
tPennies.setText(""+ penny);
}
});
}
//Main Method
public static void main(String[] args) {
// TODO code application logic here
GetChange myApp = new GetChange();
}
}
To Solve the First problem(Frame not showing) insert the following after all components are added,
this.validate(); // updates frame
To add implementation to the reset button, just use .setText("");
bReset.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
tAmount.setText("");
tQuarters.setText("");
tDimes.setText("");
tNickels.setText("");
tPennies.setText("");
tTwenty.setText("");
tTen.setText("");
tFive.setText("");
tOne.setText("");
tResult.setText("");
}
});
To add implementation to the Compute Button...
bCompute.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
double Amount = Double.parseDouble(tAmount.getText());
double q = (double) Integer.parseInt(tQuarters.getText()) *.25;
double d = (double) Integer.parseInt(tDimes.getText()) *.10;
double n = (double) Integer.parseInt(tNickels.getText()) *.05;
double p = (double) Integer.parseInt(tPennies.getText()) *.01;
double T = (double) Integer.parseInt(tTwenty.getText()) *20;
double Ten = (double) Integer.parseInt(tTen.getText()) *10;
double Five = (double) Integer.parseInt(tFive.getText()) *5;
double one = (double) Integer.parseInt(tOne.getText()) *1;
double TotalPaid = q+d+n+p+T+Ten+Five+1;
double diff = TotalPaid-Amount;
//Heres an example to create how many twenties you need
int totalTwenties = (int)diff /20;
diff = diff%20;
tTwenty.setText("" + totalTwenties);
}
});
Basically, I got the difference between Amount paid and Amount Cost.
A) Then, the number of times a 20 can fit into the difference is found by /20. Next, I modulus or found the remainder of the difference and twenty.
B) To Find the number of other coins/bills that you need to give as change, repeat the process described in A.

How to Print on JTextArea

I'm learning to program in Java and I'm creating my first GUI App. It about creating 100 random numbers. I did it first on cmd like this:
public class RandomNumbers {
public static void main(String[] args){
float n = 100;
float m = 1513;
float a = 19713;
float x = 177963;
float c = 1397;
float r;
float i;
for(i=0;i<=n;i++){
r = (a*x+c)%m;
x = r;
r = r/m;
System.out.println(r);
}
}
}
For some reason when i try to print the 100 random numbers on a text area, it only prints me one.This is the code:
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
public class GUIRandomNumbers extends JFrame implements ActionListener{
public JTextArea area;
public JScrollPane scroll;
public JButton button;
public RandomNumbers(){
setLayout(null);
area = new JTextArea();
area.setEditable(false);
scroll = new JScrollPane(area);
scroll.setBounds(10, 10, 400, 300);
add(scroll);
button = new JButton("Generate");
button.setBounds(10, 650, 100, 25);
add(button);
button.addActionListener(this);
}
public void actionPerformed(ActionEvent e){
float n = 100;
float m = 1513;
float a = 19713;
float x = 177963;
float c = 1397;
float r;
float i;
if(e.getSource()==button){
for(i=0;i<=n;i++){
r = (a*x+c)%m;
x = r;
r = r/m;
area.setText(String.valueOf(r));
}
}
}
public static void main(String[] args) {
RandomNumbers p1 = new RandomNumbers();
p1.setBounds(0, 0, 500, 750);
p1.setVisible(true);
}
}
What could be the problem? I will really appreciae your help.
Thanks in advance.
when you do
area.setText(String.valueOf(r));
it overwrites the text on the text area with the new text.
you should use
area.append(String);
method instead.
Use this
area.append(String.valueOf(r) + "\n\r");
instead of
area.setText(String.valueOf(r));
setText(String) method replace the previous text. Use area.append(String) method.
Accordint to docs
Appends the given text to the end of the document. Does nothing if the model is null or the string is null or empty.
At first I suppose that you mean
GUIRandomNumbers p1 = new GUIRandomNumbers();
The reason that makes you see only one number is that one number is written above the other.
I mean that you write 100 times a random number in the textArea!
area.append("text");
is the method that will do your job!

Java Sorting data from a file using JCheckboxes

I'm trying to create a program that will take data in from a random access file and sort it based on whichever checkbox the user selects. The data should be sorted by either the bank account number, customer name or balance (when a user clicks that checkbox the data in the text area becomes sorted based on that). Once the data is sorted, it is outputted into the JTextArea. I'm also trying to output the total amount of entries from the file in the text field below the check boxes.
Thanks!
import java.lang.reflect.Array;
import java.nio.file.*;
import java.text.DecimalFormat;
import java.util.Collections;
import java.io.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.*;
import javax.swing.border.Border;
public class GUIBankAcctSorter extends JFrame implements ItemListener {
public static void main(String[] args) {
GUIBankAcctSorter myFrame = new GUIBankAcctSorter();
myFrame.setVisible(true);
Path file = Paths.get("C:\\Java\\Bank.txt");
final String ID_FORMAT = "0000";
final String NAME_FORMAT = " ";
final int NAME_LENGTH = NAME_FORMAT.length();
final String BALANCE_FORMAT = "00000.00";
String delimiter = ",";
String s = ID_FORMAT + delimiter + NAME_LENGTH + delimiter + BALANCE_FORMAT + System.getProperty("line.separator");
final String EMPTY_ACCT = "0000";
String[] array = new String[3];
double balance = 0;
output(s, array, delimiter, balance, EMPTY_ACCT, file);
}
private static final long serialVersionUID = 1L;
private static final int WIDTH = 450;
private static final int HEIGHT = 310;
private static final int X_ORIGIN = 200;
private static final int Y_ORIGIN = 200;
JLabel title = new JLabel("Bank Account Sorter");
JLabel sort = new JLabel("Sort By ");
JLabel total = new JLabel("Total # of Bank Accounts ");
private Container con = getContentPane();
private FlowLayout layout = new FlowLayout();
static JTextArea area = new JTextArea(10, 35);
static JTextField field = new JTextField(5);
JCheckBox cust = new JCheckBox(" Cust # ", false);
JCheckBox bal = new JCheckBox(" Balance ", false);
JCheckBox name = new JCheckBox(" Name ", false);
public static void output(String s, String[] array, String delimiter, double balance, String EMPTY_ACCT, Path file){
String temp = "";
try{
InputStream iStream = new BufferedInputStream(Files.newInputStream(file));
BufferedReader reader = new BufferedReader(new InputStreamReader(iStream));
while(s != null){
array = s.split(delimiter);
if(!array[0].equals(EMPTY_ACCT)){
balance = Double.parseDouble(array[2]);
area.append("Cust # " + array[0] + "\t" + " Name: " + array[1] + " Balance " + "\t$" + array[2] + "\n");
}
s = reader.readLine();
}
reader.close();
}catch(Exception e){
System.out.println("Message: " + e);
}
field.setText(temp);
}
public GUIBankAcctSorter(){
super("Bank Account Sorter");
Font headFont = new Font("Arial", Font.BOLD, 28);
con.setLayout(layout);
title.setFont(headFont);
con.add(title);
area.setEditable(false);
field.setEditable(false);
con.add(new JScrollPane(area));
cust.addItemListener(this);
bal.addItemListener(this);
name.addItemListener(this);
con.add(sort);
con.add(cust);
con.add(bal);
con.add(name);
con.add(total);
con.add(field);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(X_ORIGIN, Y_ORIGIN, WIDTH, HEIGHT);
setResizable(false);
setLocationRelativeTo(null);
}
public void itemStateChanged(ItemEvent e) {
Object source = e.getSource();
int select = e.getStateChange();
if(source == cust){
if(select == ItemEvent.SELECTED){
bal.setSelected(false);
name.setSelected(false);
}
}
if(source == bal){
if(select == ItemEvent.SELECTED){
cust.setSelected(false);
name.setSelected(false);
}
}
if(source == name){
if(select == ItemEvent.SELECTED){
cust.setSelected(false);
bal.setSelected(false);
}
}
}
}
Here you can see a good example using comparator to sort the object.
Let us suppose:
RowTest is a class that represent a single row of grid.
orderAMT is a class variable/Column/JTextField of Row.
Now the code below show how to sort the List of RowTest according to its attribute orderAMT.
List<RowTest> sortedList = getAllRowsThatNeedToBeSorted();
Comparator comparator = new OrderAMTComparator();
Collections.sort(sortedList, comparator);
public class OrderAMTComparator implements Comparator<RowTest> {
#Override
public int compare(RowTest o1, RowTest o2) {
//Here you can use If condition to check which checkbox is selected and sort the list
//repace getOrderAMT with other fields.
BigDecimal compareRes = o1.getOrderAMT().getBigdecimalValue().subtract(o2.getOrderAMT().getBigdecimalValue());
//You can just return compareRes.compareTo(new BigDecimal(0))
//But Here I want to show that you can check any condition and return -1,1,0 as your
//requirement
if (compareRes.compareTo(new BigDecimal(0)) == -1) {
return -1;
} else if (compareRes.compareTo(new BigDecimal(0)) == 1) {
return 1;
} else if (compareRes.compareTo(new BigDecimal(0)) == 0 ) {
return 0;
}
return compareRes.intValue();
}
}
I hope you have understand this. If not I will elaborate.
Thankyou.
Is there anyway to do it with checkboxes?
Certainly:
Declare an Account class that stores the account number, name & balance.
Add each new Account to a List structure such as ArrayList.
Create a Comparator relevant to each of the 2 fields.
At time of sort, use Collections.sort(list,comparator).
Refresh the text area with the content of the sorted list.
Other tips
Since those check boxes are mutually exclusive, they should really be a ButtonGroup of JRadioButton instances.
Change setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); to setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); & setLocationRelativeTo(null) to setLocationByPlatform(true). See this answer for a demo.
Change setBounds(X_ORIGIN, Y_ORIGIN, WIDTH, HEIGHT); for pack() (& use layouts more effectively).

Retrieving a double from a JTextArea while solving for X

Ok, I'm kinda new to java. I'm making a program that solves for one step equations. I'm having some difficulties running it though. Here is the code for my main file, Main.java:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Main extends JFrame implements ActionListener {
private static final long serialVersionUID = 1L;
Solve solve = new Solve();
JButton add = new JButton("Add");
JButton sub = new JButton("Subtract");
JButton mult = new JButton("Multiply");
JButton div = new JButton("Divide");
JButton solv = new JButton("Solve!");
JTextArea one = new JTextArea();
JLabel two = new JLabel(" = ");
JLabel three = new JLabel("X");
JLabel four = new JLabel();
JTextArea five = new JTextArea();
JLabel solved = new JLabel();
JPanel row1 = new JPanel();
JPanel row2 = new JPanel();
JPanel row3 = new JPanel();
public double funct;
public Main() {
super("Solving a one step equation!");
setSize(500, 500);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
GridLayout layout = new GridLayout();
setLayout(layout);
FlowLayout layout1 = new FlowLayout(FlowLayout.CENTER);
row1.setLayout(layout1);
row1.add(add);
row1.add(sub);
row1.add(mult);
row1.add(div);
row1.add(solv);
add(row1);
add.addActionListener(this);
sub.addActionListener(this);
mult.addActionListener(this);
div.addActionListener(this);
solv.addActionListener(this);
GridLayout layout2 = new GridLayout(1, 1, 1, 1);
row2.setLayout(layout2);
row2.add(one, BorderLayout.CENTER);
row2.add(two, BorderLayout.CENTER);
row2.add(three, BorderLayout.CENTER);
row2.add(four, BorderLayout.CENTER);
row2.add(five);
add(row2, BorderLayout.CENTER);
GridLayout layout3 = new GridLayout(5, 5, 5, 5);
row3.setLayout(layout3);
row3.add(solved);
add(row3);
}
public static void main(String[] args) {
Main frame = new Main();
}
public void actionPerformed(ActionEvent evt) {
Object source = evt.getSource();
if(source == add)
{
four.setText(" + ");
funct = 1;
}
else if(source == sub)
{
four.setText(" - ");
funct = 2;
}
else if(source == mult)
{
four.setText(" * ");
funct = 3;
}
else if(source == div)
{
four.setText(" / ");
funct = 4;
}
if(source == solv)
{
if(funct == 1)
{
double Ones = Double.parseDouble(three.getText());
double Twos = Double.parseDouble(three.getText());
solved.setText("X = " + solve.Add(Ones, Twos));
}
else if(funct == 2)
{
double Ones = Double.parseDouble(three.getText());
double Twos = Double.parseDouble(three.getText());
solved.setText("X = " + solve.Sub(Ones, Twos));
}
else if(funct == 3)
{
double Ones = Double.parseDouble(three.getText());
double Twos = Double.parseDouble(three.getText());
solved.setText("X = " + solve.Mult(Ones, Twos));
}
else if(funct == 4)
{
double Ones = Double.parseDouble(three.getText());
double Twos = Double.parseDouble(three.getText());
solved.setText("X = " + solve.Div(Ones, Twos));
}
}
}
}
Here is the code for my other file, Solve.java
public class Solve {
public double Add(double One, double Two)
{
return One - Two;
}
public double Sub(double One, double Two)
{
return One + Two;
}
public double Mult(double One, double Two)
{
return One / Two;
}
public double Div(double One, double Two)
{
return One * Two;
}
}
Some help would be appreciated. Anyone see what I'm doing wrong?
You get a NumberFormatException once 'Solve' button is clicked. It seems like a copy/paste issue - you are not retrieving the correct numbers. You are trying to convert 'X' string to double. It is best if you give meaningful names to your variables. To fix the exception, try this, replace :
double Ones = Double.parseDouble(three.getText());
double Twos = Double.parseDouble(three.getText());
with:
double Ones = Double.parseDouble(one.getText());
double Twos = Double.parseDouble(five.getText());
Get familiar with Java Code Conventions, Naming Conventions section in particular.
In addition to #Max's helpful answer, here are a few other suggestions:
Setting the frame's layout to new GridLayout() defaults to a single row and column with no padding. As an alternative, consider new GridLayout(0, 1, 5, 5), which produces any number of rows in one column with 5x5 padding. Then you can focus on the layout of each row:
row1.setLayout(new FlowLayout(FlowLayout.CENTER));
row2.setLayout(new FlowLayout(FlowLayout.CENTER));
row3.setLayout(new GridLayout(1, 1, 5, 5));
Move your setVisible() call to the end of the frame's constructor:
pack();
setLocationRelativeTo(null);
setVisible(true);
Consider getRootPane().setDefaultButton(solv) to make the Solve button the default.
Consider making addition the default:
private JLabel four = new JLabel("+");
private int funct = 1; // add by default
Consider using JTextField for number entry:
private JTextField one = new JTextField(10);
private JTextField five = new JTextField(10);

Java: Calling a class within a for loop

I've just started learning Java, so I apologize if this question is somewhat basic, and I'm sure my code is not as clean as it could be. I've been trying to write a small quiz program that will input a list of German verbs from a txt file (verblist.txt). Each line of the text file contains five strings: the German verb (verbger), the English translation (verbeng), the praeteritum and perfekt conjugations conjugations (verbprae and verbperf) and whether it uses haben or sein as the auxiliary verb (H or S, stored as verbhaben). The verb set is chosen by generating a random number and selecting the "row" of the two dimensional array. The GUI then displays the first two variables, and the user has to input the last three. If the last three match the values in the txt file, the user gets it correct and moves on to another verb.
I'm at the point where the code is working the way I want it to - for one verb. The way I've been organizing it is in two classes. One, VerbTable, imports the text file as a two dimensional array, and the other, RunVerb, generates the GUI and uses an ActionListener to compare the user input to the array. What I can't figure out now is how, after the user gets one verb set correct, I can then loop through the entire set of verbs.
I was thinking of creating a for loop that loops through the number of rows in the text file (saved in the code as height), generating a new random number each time to select a different verb set (or "row" in the two dimensional array.) Essentially, I'd like to get a loop to run through the entire VerbRun class, and pause for the ActionListener, until all of the verb sets have been displayed.
Here is the VerbTable class, which generates the array and random number to select the row:
package looptest;
import java.io.*;
import java.util.*;
public class VerbTable {
public int width;
public int height;
public int randnum;
public String verbger = new String("");
public String verbeng = new String("");
public String verbprae = new String("");
public String verbperf = new String("");
public String verbhaben = new String("");
public VerbTable() {
File file = new File("verblist.txt");
try {
/* For array height and width */
Scanner scanner1 = new Scanner(file).useDelimiter("\n");
int height = 0;
int width = 0;
while (scanner1.hasNextLine()) {
String line = scanner1.nextLine();
height++;
String[] line3 = line.split("\t");
width = line3.length;
}
System.out.println("Height: " + height);
System.out.println("Width: " + width);
this.width = width;
this.height = height;
/* Array height/width end */
/* random number generator */
int randnum1 = 1 + (int)(Math.random() * (height-1));
this.randnum = randnum1;
/* random number generator end */
Scanner scanner = new Scanner(file).useDelimiter("\n");
String verbtable[][];
verbtable = new String[width][height];
int j = 0;
while (scanner.hasNextLine()){
String verblist2 = scanner.next();
String[] verblist1 = verblist2.split("\t");
System.out.println(verblist2);
verbtable[0][j] = verblist1[0];
verbtable[1][j] = verblist1[1];
verbtable[2][j] = verblist1[2];
verbtable[3][j] = verblist1[3];
verbtable[4][j] = verblist1[4];
j++;
}
this.verbger = verbtable[0][randnum];
this.verbeng = verbtable[1][randnum];
this.verbprae = verbtable[2][randnum];
this.verbperf = verbtable[3][randnum];
this.verbhaben = verbtable[4][randnum];
}
catch (FileNotFoundException e){
e.printStackTrace();
}
}
public int getRand(){
return this.randnum;
}
public int getWidth(){
return this.width;
}
public int getHeight(){
return this.height;
}
public String getVerbger(){
return this.verbger;
}
public String getVerbeng(){
return this.verbeng;
}
public String getVerbprae(){
return this.verbprae;
}
public String getVerbperf(){
return this.verbperf;
}
public String getVerbhaben(){
return this.verbhaben;
}
public static void main(String[] args) throws IOException {
}
}
And here is the RunVerb class:
package looptest;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class RunVerb extends JFrame {
VerbTable dimensions = new VerbTable();
int width = dimensions.getWidth();
int height = dimensions.getHeight();
int randnum = dimensions.getRand();
String verbgerin = dimensions.getVerbger();
String verbengin = dimensions.getVerbeng();
String verbpraein = dimensions.getVerbprae();
String verbperfin = dimensions.getVerbperf();
String verbhabenin = dimensions.getVerbhaben();
String HabenSeinSelect = new String("");
public JTextField prae = new JTextField("",8);
public JTextField perf = new JTextField("",8);
public JLabel verbger = new JLabel(verbgerin);
public JLabel verbeng = new JLabel(verbengin);
public JRadioButton haben = new JRadioButton("Haben");
public JRadioButton sein = new JRadioButton("Sein");
public RunVerb() {
JButton enter = new JButton("Enter");
enter.addActionListener(new ConvertBtnListener());
prae.addActionListener(new ConvertBtnListener());
perf.addActionListener(new ConvertBtnListener());
JPanel content = new JPanel();
content.setLayout(new FlowLayout());
content.add(verbger);
verbger.setBorder(BorderFactory.createEmptyBorder(15, 20, 15, 20));
content.add(verbeng);
verbeng.setBorder(BorderFactory.createEmptyBorder(15, 20, 15, 40));
content.add(new JLabel("Praeteritum:"));
content.add(prae);
content.add(new JLabel("Perfekt:"));
content.add(perf);
content.add(haben);
haben.setBorder(BorderFactory.createEmptyBorder(0, 20, 0, 10));
haben.setSelected(true);
content.add(sein);
sein.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 10));
ButtonGroup bg = new ButtonGroup();
bg.add(haben);
bg.add(sein);
content.add(enter);
setContentPane(content);
pack();
setTitle("Verben");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
class ConvertBtnListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
String outprae = prae.getText();
int praenum = 0;
if (outprae.equals(verbpraein)){
praenum = 1;
}
String outperf = perf.getText();
int perfnum = 0;
if (outperf.equals(verbperfin)){
perfnum = 1;
}
boolean habenselect = haben.isSelected();
boolean seinselect = sein.isSelected();
if (habenselect == true){
HabenSeinSelect = "H";
}
else {
HabenSeinSelect = "S";
}
int habennum = 0;
if (HabenSeinSelect.equals(verbhabenin)) {
habennum = 1;
}
int numtot = praenum + perfnum + habennum;
if (numtot == 3){
System.out.println("Correct.");
}
else{
System.out.println("Incorrect.");
}
numtot = 0;
}
}
public static void main(String[] args) {
window.setVisible(true);
}
}
So what would be the best way to cycle through the entire verbtable array until all of the rows have been displayed? Should I create a for loop, and if so, where should it go? Should I make a new class that contains the loop and references the VerbRun class? If so, what would be the best way to go about it?
I hope this makes sense! Thank you!
To go through all the verbs exactly in a random order, you may not want to generate random numbers each time, as the random number can repeat. You have to create a random permutation of verbs, one way to do it is Collections.shuffle
see http://download.oracle.com/javase/6/docs/api/java/util/Collections.html
Also You dont have to create a new RunVerb Object, instead create once, and use setters to change the UI, and the functionality of Action Listeners. So pseudo code would be
Collections.shuffle(verbsList);
for(verb : verbsList)
{
setLabel1(verb[0]);
setLabel2(verb[1]);...
}
I would have a method like getNextRandomVerb() in then VerbTable class that generates the next verb to be shown. It will keep track of the verbs that have been shown ( for a given user-session ofcourse ) already and ensure the next one picked is not a repeat. Your RunVerb class seems to more responsible for managing the GUI , so this is not the place to define how to get the next verb to display.

Categories