How do I switch the end function? - java

As in, the value as the end where it says "X dollars converts to Y russian ruble" (after the two Digits new Decimal Format) - the problem is that it can be russian ruble, british pound, or euro. How can I differentiate? (text inserted at line in question)
import java.awt.*;
import java.applet.*;
import java.awt.event.*;
import java.text.DecimalFormat;
public class CurrencyConversion extends Applet implements ItemListener
{
//declare variables and color
double dollars, answer;
int empCode;
Image dollarSign;
Color darkRed = new Color(160, 50, 0);
//Create components for applet
Label promptLabel = new Label("Enter the dollar amount (do not use commas or dollar signs):");
TextField currencyField = new TextField(20);
Label codeLabel = new Label ("Select the desired currency:");
CheckboxGroup codeGroup = new CheckboxGroup () ;
Checkbox britishpoundBox = new Checkbox("British Pound",false,codeGroup);
Checkbox euroBox = new Checkbox("Euro",false,codeGroup);
Checkbox russianrubleBox = new Checkbox("Russian Ruble",false,codeGroup);
Checkbox hiddenBox = new Checkbox("",true,codeGroup);
Label outputLabel = new Label("Click an option to convert the desired currency.");
public void init()
{
setBackground(darkRed);
setForeground(Color.white);
add(promptLabel);
add(currencyField);
currencyField.requestFocus();
currencyField.setForeground(Color.black);
add(codeLabel);
add(britishpoundBox);
britishpoundBox.addItemListener(this);
add(euroBox);
euroBox.addItemListener(this);
add(russianrubleBox);
russianrubleBox.addItemListener(this);
add(outputLabel);
}
//This method is triggered by click
public void itemStateChanged(ItemEvent choice)
{
try
{
dollars = getCurrency();
empCode = getCode();
answer = getComm(dollars,empCode);
output(answer, dollars);
}
catch (NumberFormatException e)
{
outputLabel.setText("You must enter a dollar amount greater than zero.");
hiddenBox.setState(true);
currencyField.setText("");
currencyField.requestFocus();
}
}
public double getCurrency()
{
double currency = Double.parseDouble(currencyField.getText());
if (currency <= 0) throw new NumberFormatException();
return currency;
}
public int getCode()
{
int code = 0;
if (britishpoundBox.getState()) code = 1;
else
if (euroBox.getState()) code = 2;
else
if (russianrubleBox.getState()) code = 3;
return code;
}
public double getComm(double currency, int code)
{
double amount = 0.0;
switch(code)
{
case 1:
amount = .79610 * currency;
break;
case 2:
amount = .70880 * currency;
break;
case 3:
amount = 35.88240 * currency;
break;
}
return amount;
}
public void output(double amount, double currency)
{
DecimalFormat twoDigits = new DecimalFormat("##.00");
outputLabel.setText("Your amount of " + twoDigits.format(currency) + " dollars converts to " + twoDigits.format(amount) RIGHT HERE - what do I do? );
}
public void paint(Graphics g)
{
dollarSign = getImage(getDocumentBase(), "dollarsign.gif");
g.drawImage(dollarSign,12,28,this);
}
}

Create a mapping from Integer to String, populate it with the various currency descriptions, and pass the Integer to the output function so that you can get the description from the mapping.

Wrap the currency concept into its own object. Override the ToString() method and return the name of the currency or define an explicit property to return the currency type. Pass the currency object around instead of the not so complex double and make the rate which was previously the double a property on the object.

I'd suggest you to use class java.util.Currency. The exchange rate of each currency should not be hard coded. For first phase just put it into properties file, i.e.:
RUB=35.88240
GBP=.79610
Avoid using hard coded list of currencies. Instead parse this property file, extract all keys, then use Currency.getInstance(currencyCode). Both UI and logic will be generic. Your application will be at least twice shorter and much more flexible.

Related

Read from a file and populate existing JComboBox with new data

I am attempting to write a conversion program in which a new file can be loaded in to the program and change the conversion (needs to also include validation if the file is corrupted). I currently have the conversions hard coded in and want to extend the program so that it accepts the conversion factors from an external txt file.
I am new to programming and don't really understand how to do this can someone help?
public class CurrencyPanel extends JPanel{
//Declaring global variables which include buttons, labels, comboBox and a CheckBox
private final static String[] conversionList = { "Euro (EUR)", "US Dollers(USD)", "Australian Dollars (AUD)",
"Canadian Dollars (CAD)", "Icelandic Króna (ISK)", "United Arab Emirates Dirham (AED)",
"South African Rand (ZAR)", "Thai Baht (THB)"};
private JTextField inputField;
private JLabel labelOutput, labelCount, labelReverse;
private JCheckBox reverseCheck;
private JComboBox<String> comboSelect;
private int count = 0;
public MainPanel mainPanel;
CurrencyPanel() {
//initialising the convertListner to listener
ActionListener listener = new ConvertListener();
//setting comboBox to variable of list of conversions
comboSelect = new JComboBox<String>(conversionList);
comboSelect.setToolTipText("Select Conversion Type"); //ToolTip
JLabel labelEnter = new JLabel("Enter value:"); //enter value label
JButton convertButton = new JButton("Convert"); //convert button
convertButton.addActionListener(listener); // convert values when pressed
convertButton.setToolTipText("Press to convert value"); //ToolTip
JButton clearButton = new JButton ("Clear"); //clear button
clearButton.addActionListener(new ClearLabel()); //clear labels when button pressed
clearButton.setToolTipText("Press to Clear Value & Conversion Counter"); //ToolTip
labelOutput = new JLabel("---"); //label to be changed when conversion done
inputField = new JTextField(5); //textField for the user to input
inputField.addActionListener(listener); //Press return to do conversion
labelOutput.setToolTipText("Conversion Value"); //ToolTip
inputField.setToolTipText("Enter the value you wish to convert"); //ToolTip
labelCount = new JLabel("Conversion Count: 0"); //Conversion count label to be changed when conversion occurs
labelCount.setToolTipText("Amount of conversions made"); //ToolTip
labelReverse = new JLabel("Reverse Conversion"); //ReverseConversion label
reverseCheck = new JCheckBox(); //new CheckBox
reverseCheck.setToolTipText("Check the box to reverse the conversion type"); //ToolTip
//adding components to the panel
add(comboSelect);
add(labelEnter);
add(inputField);
add(convertButton);
add(labelOutput);
//setting size and colour of panel
setPreferredSize(new Dimension(800, 100));
setBackground(Color.cyan);
}
public void clearLabelMethod() {
labelOutput.setText("---");
inputField.setText("");
count = 0;
labelCount.setText("Conversion Count: 0");
}
//ActionListener to clear labels
private class ClearLabel implements ActionListener{
#Override
public void actionPerformed(ActionEvent e)
{
labelOutput.setText("---");
inputField.setText("");
count = 0;
labelCount.setText("Conversion Count: 0");
}
}
//ActionListener that does the main conversions
private class ConvertListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent event) {
String text = inputField.getText().trim();
//attempting to clear the combo box before repopulating
comboSelect.removeAllItems();
//try block to display message dialog
try {
Double.parseDouble(text); //checking to see if value is an double
if(inputField.getText().isEmpty())
{ //if statement to check if inputField is empty
}
}catch (Exception e) {
JOptionPane.showMessageDialog(null, "Please enter a valid number"); //message dialogue
return;
}
// if exception isn't thrown, then it is an integer
if (text.isEmpty() == false) {
double value = Double.parseDouble(text); //converting double to string
// the factor applied during the conversion
double factor = 0;
// the offset applied during the conversion.
double offset = 0;
String symbol = null;
// Setup the correct factor/offset values depending on required conversion
switch (comboSelect.getSelectedIndex()) {
case 0: // Euro
factor = 1.359;
symbol = "€";
break;
case 1: // USD
factor = 1.34;
symbol = "$";
break;
case 2: // AUD
factor = 1.756;
symbol = "$";
break;
case 3: // CAD
factor = 1.71;
symbol = "$";
break;
case 4: // ISK
factor = 140.84;
symbol = "kr";
break;
case 5: // AED
factor = 4.92;
symbol = "د.إ";
break;
case 6: // ZAR
factor = 17.84;
symbol = "R";
break;
case 7: // THB
factor = 43.58;
symbol = "฿";
break;
}
double result = 0;
if(mainPanel.reverseCheckMethod() == true) { //if the reverse check option is selected
result = value / factor - offset; //do the opposite conversion
}else {
result = factor * value + offset; //if not then do regular conversion
}
DecimalFormat decFormat = new DecimalFormat("0.00"); //DecimalFormat of output
String formatted = decFormat.format(result); //formatting the result 2 decimal places
mainPanel.conCount();
labelOutput.setText(symbol+formatted); //setting the output label
}
}
}
public void loadFile() {
int itemCount = comboSelect.getItemCount();
for(int i=0;i<itemCount;i++) {
comboSelect.removeAllItems();
}
try {
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("currency.txt"), "UTF8"));
String line = null;
while ((line = br.readLine()) != null) {
String[] values = line.split(",");
String currencyType = values[0];
String currencyValueTxt = values[1];
String currencySymbol = values[2];
Double conversionValue = Double.parseDouble(currencyValueTxt);
comboSelect.addItem(currencyType);
br.close();
}
}catch(Exception e) {
JOptionPane.showMessageDialog(null, "File Error");
}
}
}
The currency file in question is encoded in UTF-8 and is as follows:
Euro (EUR), 1.41, €
US Dollars (USD), 1.24, $
Australian Dollars (AUD), 1.86, $
Bermudan Dollar (BMD), 1.35, $
Icelandic króna (ISK), 141.24, kr
United Arab Emirates Dirham (AED), 4.12, د.إ
South African Rand (ZAR), 16.84, R
Thai Baht (THB), 42.58, ฿
Well you want to start to use a custom object to hold related data.
So you would start by creating a Currency object with 3 properties:
Name
Rate
Symbol
Something like:
public class Currency
{
private String name;
private double rate;
private String symbol;
public Currency (String name, double rate, String symbol)
{
this.name = name;
this.rate = rate;
this.symbol = symbol;
}
// add getter methods here
#Override
public String toString()
{
return name;
}
}
You would then need to add getter methods, getName(), getRate() and getSymbol() so you can access the data from the object.
Now you can add the "hard coded" currency objects to your combo box with code like:
//comboSelect = new JComboBox<String>(conversionList);
comboSelect = new JComboBox<Currency>();
comboSelect.addItem( new Currency("Euro (EUR)", 1.23, "€") );
comboSelect.addItem( new Currency("US Dollar (USD), 1.23, "$") );
...
The default renderer for the combo box will invoke the toString() method of your Currency object for the text to display in the combo box.
Now the ActionListener code for you combo box is greatly simplified:
Currency currency = (Currency)comboSelect.getSelectedItem();
factor = currency.getRate();
symbol = currency.getSymbol();
No need for the switch statement.
In your current design you have the names hard code in an Array and the rate/symbol hard coded in the ActionListener. With this design you have all the data together in a simple object.
So first get this basic logic working with hard coded Currency objects.
Then when you are ready to create dynamic currency objects your looping code would be something like:
while ((line = br.readLine()) != null)
{
String[] values = line.split(",");
double rate = Double.parseDouble( values[1] );
Currency currency = new Currency(values[0], rate, values[2]);
comboSelect.addItem( currency);
//br.close(); you only close the file after reading all the lines of data
}
br.close();
Note: it really isn't a good idea to use the toString() method for the text to display in the combo box. Instead you should be using a custom renderer. Once you have gotten the above suggestions working you can check out: Combo Box With Custom Renderer for more information on this topic.

Converting a program to use arrays INSTEAD of ArrayLists

I have a class ShoppingCart that utilizes ArrayList methods to carry out the program which is basically a program where you add groceries to your cart and such. However, I want to use arrays to do the program instead of ArrayLists since I want to work on my array knowledge. Here is the ShoppingCart class
import java.util.*;
#SuppressWarnings("serial")
public class ShoppingCart extends ArrayList<Selections> {
// FIELDS
private boolean discount;
// Selections[]......
// CONSTRUCTOR
public ShoppingCart() {
super();
discount = false;
}
// Adding to the Collection
public boolean add(Selections next) {
// check to see if it's already here
for (int i = 0; i < this.size(); i++)
if (get(i).equals(next)) {
set(i, next); // replace it
return true;
}
super.add(next); // add new to the array
return false;
}
// The GUI only know if check is on or off
public void setDiscount(boolean disc) {
discount = disc; // match discount from GUI
}
// total of selections
public double getTotal() {
double sum = 0.0;
for (int i = 0; i < this.size(); i++)
sum += get(i).priceFor();
if (discount) sum *= 0.9;
return sum;
}
}
The Selections class that is being used for the individual groceries.
import java.text.*;
// W.P. Iverson, instructor
// January 2018 for CS211
// Class that combines Item and ItemOrder
public class Selections {
// FIELDS
private String name; // friendly name
private double price; // cost of one
private int bulkQuantity; // when bulk price kicks in
private double bulkPrice; // price for the bulk quantity
private int quantity; // how many we are buying
private boolean hasBulk; // internally used
private NumberFormat curr; // for nice $12.34 currency formatting
// CONSTRUCTORS
public Selections(String name, double price) {
this(name, price, -99999, 99999.); // flag that nothing is selected with 99999
}
public Selections(String thing, double amount, int qty, double bulk) {
name = thing;
price = amount;
if (qty > 0) hasBulk = true;
bulkQuantity = qty;
bulkPrice = bulk;
quantity = 0; // starts with zero selected by user, GUI changes it later
curr = NumberFormat.getCurrencyInstance();
}
// decides how many we're buying
public void setQuantity(int number) {
quantity = number;
}
// calculates the price for this quantity
public double priceFor() {
if (hasBulk && quantity >= bulkQuantity)
return quantity / bulkQuantity * bulkPrice + quantity % bulkQuantity * price;
else
return quantity * price;
}
// basic output for console or GUI text
public String toString() {
if (hasBulk)
return name + ", " + curr.format(price) + " (" + bulkQuantity + " for " + curr.format(bulkPrice) + ")";
else
return name + ", " + curr.format(price);
}
}
I made a JFrame for the program already but just want to get it to use regular arrays instead! Thanks for your help.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.text.*;
#SuppressWarnings("serial")
public class ShoppingFrame extends JFrame {
private ShoppingCart items;
private JTextField total;
public ShoppingFrame(Selections[] array) {
// create frame and order list
setTitle("CS211 Shopping List");
setDefaultCloseOperation(EXIT_ON_CLOSE);
items = new ShoppingCart();
// set up text field with order total
total = new JTextField("$0.00", 12);
total.setEditable(false);
total.setEnabled(false);
total.setDisabledTextColor(Color.BLACK);
JPanel p = new JPanel();
p.setBackground(Color.blue);
JLabel l = new JLabel("order total");
l.setForeground(Color.YELLOW);
p.add(l);
p.add(total);
add(p, BorderLayout.NORTH);
p = new JPanel(new GridLayout(array.length, 1));
for (int i = 0; i < array.length; i++)
addItem(array[i], p);
add(p, BorderLayout.CENTER);
p = new JPanel();
add(makeCheckBoxPanel(), BorderLayout.SOUTH);
// adjust size to just fit
pack();
}
// Sets up the "discount" checkbox for the frame
private JPanel makeCheckBoxPanel() {
JPanel p = new JPanel();
p.setBackground(Color.blue);
final JCheckBox cb = new JCheckBox("qualify for discount");
p.add(cb);
cb.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
items.setDiscount(cb.isSelected());
updateTotal();
}
});
return p;
}
// adds a product to the panel, including a textfield for user input of
// the quantity
private void addItem(final Selections product, JPanel p) {
JPanel sub = new JPanel(new FlowLayout(FlowLayout.LEFT));
sub.setBackground(new Color(0, 180, 0));
final JTextField quantity = new JTextField(3);
quantity.setHorizontalAlignment(SwingConstants.CENTER);
quantity.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
updateItem(product, quantity);
quantity.transferFocus();
}
});
quantity.addFocusListener(new FocusAdapter() {
public void focusLost(FocusEvent e) {
updateItem(product, quantity);
}
});
sub.add(quantity);
JLabel l = new JLabel("" + product);
l.setForeground(Color.white);
sub.add(l);
p.add(sub);
}
// When the user types a new value into one of the quantity fields,
// parse the input and update the ShoppingCart. Display an error
// message if text is not a number or is negative.
private void updateItem(Selections product, JTextField quantity) {
int number;
String text = quantity.getText().trim();
try {
number = Integer.parseInt(text);
} catch (NumberFormatException error) {
number = 0;
}
if (number <= 0 && text.length() > 0) {
Toolkit.getDefaultToolkit().beep();
quantity.setText("");
number = 0;
}
product.setQuantity(number);
items.add(product);
updateTotal();
}
// reset the text field for order total
private void updateTotal() {
double amount = items.getTotal();
total.setText(NumberFormat.getCurrencyInstance().format(amount));
}
public static void main(String[] args) {
Selections[] array = new Selections[10];
array[0] = new Selections("silly putty", 3.95, 10, 19.99);
array[1] = new Selections("silly string", 3.50, 10, 14.95);
array[2] = new Selections("bottle o bubbles", 0.99);
array[3] = new Selections("Nintendo Wii system", 389.99);
array[4] = new Selections("Mario Computer Science Party 2 (Wii)", 49.99);
array[5] = new Selections("Don Knuth Code Jam Challenge (Wii)", 49.99);
array[6] = new Selections("Computer Science pen", 3.40);
array[7] = new Selections("Rubik's cube", 9.10);
array[8] = new Selections("Computer Science Barbie", 19.99);
array[9] = new Selections("'Java Rules!' button", 0.99, 10, 5.0);
ShoppingFrame f = new ShoppingFrame(array);
f.setVisible(true);
}
}
You can use an array member variable in ShoppingCart class like this:
private Selections[] selectionsArray;
instead of extending ArrayList<Selections>. (Then you will have to handle resizing the array yourself.)

How to access user input in a JTextField?

For a school project I am writing a program where I need to retrieve user input from a JTextField. I've tried using the getText() method, but it is returning an empty string error.
String s = input.getText();
if(changeNum.equals("")){
firstNum = s;
}
if(!changeNum.equals("")){
secondNum = s;
}
firstNum and secondNum are both strings. The error that is being returned is:
Exception in thread "AWT-EventQueue-0" java.lang.NumberFormatException: empty String
It's being returned at this line:
Double firstN = Double.parseDouble(firstNum);
What do I do? Thank you!
Edit: Forgot to add that input is the name of my JTextField, in case that is confusing.
Change all your varibles to double (firstNum etc.) and change your code like :
Note : if you not using negatIive numbers
double s = null;
try{
s = Double.parseDouble(input.getText());
}catch(NumberF... e){e.getMesssge();}
if(s > 0){
if(changeNum >= 0){
firstNum = s;
}
else {
secondNum = s;
}
}
//if you have to convert it to String use :
String str =String.valueOf(your double variable);
This is how I like to do it (in a general sense). Let's say I have a panel with three text boxes and I want to get the value of each one (each represents a different type). This is what I'd do:
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.BoxLayout;
public class Panel extends JPanel
{
JTextField textBox;
JTextField intBox;
JTextField floatBox;
JTextField dblBox;
public Panel()
{
textBox = new JTextField("Hello");
intBox = new JTextField("10");
floatBox = new JTextField("3");
dblBox = new JTextField("3.14");
this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
this.add(textBox);
this.add(intBox);
this.add(floatBox);
this.add(dblBox);
}
public String getText()
{
return textBox.getText();
}
public int getInt()
{
try
{
return Integer.parseInt( intBox.getText() );
}
catch(NumberFormatException execp) { }
return -1;
}
public float getFloat()
{
try
{
return Float.parseFloat( floatBox.getText() );
}
catch(NumberFormatException execp) { }
return -2.0f;
}
public double getDouble()
{
try
{
return Double.parseDouble( dblBox.getText() );
}
catch(NumberFormatException execp) { }
return -2.0;
}
}
Another option is to make Panel implement ActionListener, and dblBox.addActionListener(this). Then you can get your JTextField to call a method from your parent whenever you change a number, parse the data, and write error messages in a JLabel if the casting throws an exception, or to private members if it succeeded. Then use getters to read the private members.

"String cannot be converted to Component" in JOptionPane

Keep getting a "String cannot be converted to Component" in the last JOptionPane
My apologies for the awful looking format. I know using switch is much easier, this is just an assignment for my Java class. Any and all suggestions welcomed. Thankyou
import javax.swing.JOptionPane;
import java.util.*;
import java.text.*;
import java.lang.String;
public class Project4A
{
public static void main(String[] args)
{
NumberFormat formatter = NumberFormat.getCurrencyInstance();
Scanner sc = new Scanner(System.in);
double dcostBagel = 2.00; //Variables
double dcostDonut = 1.50;
double dcostCrois = 3.00;
double dcostLatte = 1.50;
double dcostCoffee = 1.25;
double dcostMilk = 1.00;
double dcostTea = 0.50;
double dfoodChoiceCost;
double dbevChoiceCost;
double dtotDue;
double dtotCost;
int ichoiceFood;
int ichoiceBev;
int inumOrdered;
String choiceFood;
String choiceBev;
String finChoiceFood;
String finChoiceBev;
//Prompts
choiceFood = JOptionPane.showInputDialog("Welcome to BeBe's Best BreakfastnChoose a Breakfast Item:n1: Bagel # "+formatter.format(dcostBagel) + "n2: Donut # "+formatter.format(dcostDonut) + "n3: Croissant # "+formatter.format(dcostCrois));
ichoiceFood = Integer.parseInt(choiceFood);
choiceBev = JOptionPane.showInputDialog("Choose one of the following beverages:nEnter:n1: Latte # "+formatter.format(dcostLatte)+"n2: Coffee # "+formatter.format(dcostCoffee)+"n3: Milk # "+formatter.format(dcostMilk)+"n4: Tea # "+formatter.format(dcostTea));
ichoiceBev = Integer.parseInt(choiceBev);
//If Elses for Food
if(ichoiceFood == 1)
{
finChoiceFood = "Bagel";
dfoodChoiceCost = dcostBagel;
}
else if(ichoiceFood == 2)
{
finChoiceFood = "Donut";
dfoodChoiceCost = dcostDonut;
}
else
{
finChoiceFood = "Croissant";
dfoodChoiceCost = dcostCrois;
}
//If Elses for Beverages
if(ichoiceBev == 1)
{
finChoiceBev = "Latte";
dbevChoiceCost = dcostLatte;
}
else if(ichoiceBev == 2)
{
finChoiceBev = "Coffee";
dbevChoiceCost = dcostCoffee;
}
else if(ichoiceBev == 3)
{
finChoiceBev = "Milk";
dbevChoiceCost = dcostMilk;
}
else
{
finChoiceBev = "Tea";
dbevChoiceCost = dcostTea;
}
/
//Retreive num ordered
System.out.println("How many items would you like?(1 to 20");
inumOrdered = sc.nextInt();
//Calculations
dtotCost = dbevChoiceCost + dfoodChoiceCost;
dtotDue = dtotCost * inumOrdered;
//Integer.toString(inumOrdered);
//Final Output
JOptionPane.showMessageDialog("Breakfast ordered:n"+finChoiceFood+" # "+formatter.format(dfoodChoiceCost)+"nnBeverage ordered:n"+finChoiceBev+" # "+formatter.format(dbevChoiceCost)+"nnTotal cost: "+formatter.format(dtotCost)+"nNumber ordered: "+inumOrdered,"Your Bill");
}
}
Your code is not matching any method signatures of the showMethodDialogue(...) function(s). Take a look at the JOptionPane Javadoc:
static void showMessageDialog(Component parentComponent, Object
message): Brings up an information-message dialog titled "Message".
static void showMessageDialog(Component parentComponent, Object
message, String title, int messageType): Brings up a dialog that
displays a message using a default icon determined by the messageType
parameter.
static void showMessageDialog(Component parentComponent, Object
message, String title, int messageType, Icon icon): Brings up a dialog
displaying a message, specifying all parameters.
The parentComponent is defined as "determines the Frame in which the dialog is displayed; if null, or if the parentComponent has no Frame, a default Frame is used".

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