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).
Related
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.)
As it states, when I attempt to insert an item into an object array via my JDialog popup, I get a NullPointerException. I reworked an existing app to create the JDialog, which opens from another application class currently named Project6(). The JDialog class, called ProcessRec(), worked fine when it ran as a standalone GUI(before I made it a JDialog).
My stacktrace is rather unhelpful in this case, as it only points to the method that is attempting to insert data into the array(which, like I said, worked fine before) and the GUI buttons that correspond to them.
The constructor for ProcessRec() accepts a ToolWarehouse() object, which matches the class that creates my object array(which is an array of objects from another class I have defined, ToolItem() ).
public ProcessRec(ToolWarehouse tools)
When it ran on it's own, ProcessRec() constructor params were empty(default).
When ProcessRec() ran as a standalone GUI for inputting data into the array, I would create an object using the default constructor like so:
ToolWareHouse tools = new ToolWarehouse();
and I would then use it's method insert() to enter data into the array.
Now that it is a JDialog, though, I was instructed to change to:
ToolWarehouse tools;
However this causes the NullPointerException because, and i'm guessing, the compiler is pointing to an object that doesn't exist. When I create a new object in ProcessRec(), as I did when it was a standalone, I no longer get this exception. However, when I attempt to store data into the array using insert(), it does not work and the data cannot be found(although I receive a prompt saying the insert was successful).
I know very little about instances of classes, but i'm assuming that the reason my data isn't showing is because it is using a whole different instance of the ToolWarehouse() class? Is the format:
public ProcessRec(ToolWarehouse tools)
accepting the same instance of the class used before? I may be way off base here, so I was hoping someone could help me understand what may be happening and why.
If more info is needed I apologize, i'll add whatever is necessary. The code is somewhat lengthy and I didn't want to take up space. Thanks a ton.
EDIT: Here is the ProcessRec() class, which creates the JDialog box, along with some of the methods corresponding to it's use.
public class ProcessRec extends JDialog
{
//global declarations
private JButton insertBtn;
private JButton deleteBtn;
private JButton displayBtn;
private JButton hideBtn;
private JButton clearBtn;
private JTextField toolFld;
private JTextField idFld;
private JTextField priceFld;
private JTextField qualityFld;
private JTextField numInStockFld;
private JTextField messageFld;
private JLabel messageLbl;
private Font f1 = new Font("serif", Font.BOLD, 24);
private Font f2 = new Font("serif", Font.PLAIN, 18);
private Container c = getContentPane();
private String input = "";
private String toolInput = "";
private int responseCode = 0;
private int idInput = 0;
private int qualityInput = 0;
private int numInStockInput = 0;
private double priceInput = 0.0;
private ToolWarehouse tools = new ToolWarehouse();
//constructor for GUI elements and event listeners
public ProcessRec(ToolWarehouse tools)
{
setTitle("Project1");
setSize(520,450);
c.setLayout(new FlowLayout());
JLabel title = new JLabel("Tiny Tim's Tool Warehouse, Inc.");
title.setFont(f1);
c.add(title);
JTextField toolLbl = new JTextField("Enter tool name:", 15);
toolLbl.setEditable(false);
c.add(toolLbl);
toolFld = new JTextField(25);
c.add(toolFld);
JTextField idLbl = new JTextField("Enter ID:", 15);
idLbl.setEditable(false);
c.add(idLbl);
idFld = new JTextField(25);
c.add(idFld);
JTextField priceLbl = new JTextField("Base Price:", 15);
priceLbl.setEditable(false);
c.add(priceLbl);
priceFld = new JTextField(25);
c.add(priceFld);
JTextField qualityLbl = new JTextField("Enter Quality:", 15);
qualityLbl.setEditable(false);
c.add(qualityLbl);
qualityFld = new JTextField(25);
c.add(qualityFld);
JTextField numInStockLbl = new JTextField("Enter Number in Stock:", 15);
numInStockLbl.setEditable(false);
c.add(numInStockLbl);
numInStockFld = new JTextField(25);
c.add(numInStockFld);
insertBtn = new JButton("Insert");
c.add(insertBtn);
deleteBtn = new JButton("Delete");
c.add(deleteBtn);
displayBtn = new JButton("Display");
c.add(displayBtn);
hideBtn = new JButton("Hide");
c.add(hideBtn);
clearBtn = new JButton("Clear");
c.add(clearBtn);
JLabel messageLbl = new JLabel("Messages:");
messageLbl.setFont(f2);
c.add(messageLbl);
messageFld = new JTextField(30);
c.add(messageFld);
//button listeners
insertBtn.addActionListener(new EventListener());
deleteBtn.addActionListener(new EventListener());
displayBtn.addActionListener(new EventListener());
hideBtn.addActionListener(new EventListener());
clearBtn.addActionListener(new EventListener());
} //end constructor
public String getToolRecords(int index)
{
return tools.getRecord(index);
}
public int getNumberOfItems()
{
return tools.getNumberOfItems();
}
//Action Listener
private class EventListener implements ActionListener
{
public void actionPerformed(ActionEvent ev)
{
if (ev.getSource() == insertBtn)
{
toolInput = toolFld.getText();
input = idFld.getText();
idInput = Integer.parseInt(input);
input = priceFld.getText();
priceInput = Double.parseDouble(input);
input = qualityFld.getText();
qualityInput = Integer.parseInt(input);
input = numInStockFld.getText();
numInStockInput = Integer.parseInt(input);
responseCode = tools.insert(qualityInput, toolInput, idInput, numInStockInput,
priceInput);
if (responseCode == 1)
{
messageFld.setText(idInput + " - Successful insertion");
}
else if (responseCode == 0)
{
messageFld.setText(idInput + " - Array is full");
}
else if (responseCode == -1)
{
messageFld.setText(idInput + " - Duplicate/Invalid ID");
}
if (tools.getNumberOfItems() < 10)
{
JOptionPane.showMessageDialog(null, "Tool Name: " + toolInput
+ "\nTool ID: " + idInput + "\nTool Base Price: " + "$" + priceInput
+ "\nQuality: " + qualityInput + "\nNumber In Stock: "
+ numInStockInput, "Insert Review", JOptionPane.INFORMATION_MESSAGE);
}
else if (tools.getNumberOfItems() == 10)
{
JOptionPane.showMessageDialog(null, "The array is full, please delete an entry",
"Insert Review", JOptionPane.INFORMATION_MESSAGE);
}
}//end insert button
else if (ev.getSource() == deleteBtn)
{
input = idFld.getText();
idInput = Integer.parseInt(input);
responseCode = tools.delete(idInput);
if (responseCode == 1)
{
messageFld.setText(idInput + " - Successful deletion");
}
else if (responseCode == -1)
{
messageFld.setText(idInput + " - ID not found");
}
}//end delete button
else if (ev.getSource() == displayBtn)
{
tools.display();
}
else if (ev.getSource() == hideBtn)
{
//setState(JFrame.ICONIFIED);
}
else if (ev.getSource() == clearBtn)
{
qualityFld.setText(null);
toolFld.setText(null);
idFld.setText(null);
numInStockFld.setText(null);
priceFld.setText(null);
messageFld.setText(null);
repaint();
}//end clear button
}//end actionPerformed
}//end ActionListener
}//end Project1
ToolWarehouse class that creates the array:
public class ToolWarehouse
{
//Global declarations
private int numberOfItems = 0;
private int index = 0;
private int returnCode = 0;
protected ToolItem[] toolArray = new ToolItem[10];
public ToolWarehouse()
{
numberOfItems = 0;
//creating the array of ToolItems
for (int i = 0; i < toolArray.length; i++)
{
toolArray[i] = new ToolItem();
System.out.println(toolArray[i]);
}
}//end constructor
public int searchArray(int id)
{
for (index = 0; index < toolArray.length; index++)
{
if (toolArray[index].getToolID() == id)
{
System.out.println("ID found at location " + index);
return index;
}
}
return -1;
}//end searchArray
public int insert(int quality, String name, int id, int numInStock, double price)
{
returnCode = searchArray(id);
if (numberOfItems == 10)
{
System.out.println("Array is full");
return 0;
}
else if (returnCode == -1)
{
boolean oK = toolArray[numberOfItems].assign(quality, name, id, numInStock,
price);
if (oK == true)
{
System.out.println("Successful insertion");
numberOfItems++;
return 1;
}
}
return -1;
}//end insert
public int delete(int ID)
{
returnCode = searchArray(ID);
if (returnCode != -1)
{
toolArray[returnCode] = new ToolItem();
for (index = returnCode; index < numberOfItems; index++)
{
toolArray[index] = toolArray[index + 1];
}
numberOfItems--;
System.out.println("Successful deletion");
return 1;
}
else
System.out.println("ID not found");
return -1;
}//end delete
public void display()
{
for (index = 0; index < numberOfItems; index++)
{
toolArray[index].calcAdjustedPrice();
toolArray[index].display();
}
}//end display
public String getRecord(int index)
{
return "Tool Name: " + toolArray[index].getName()
+ "| Tool ID: " + toolArray[index].getToolID()
+ "| Tool Quality: " + toolArray[index].getQuality()
+ "| Number in Stock: " + toolArray[index].getNumberInStock()
+ "| Tool Price: " + toolArray[index].getPrice();
}//end getRecord
public int getNumberOfItems()
{
return numberOfItems;
}
}//end ToolWarehouse
And the current portion i'm working on now, which calls insert() from the ToolWarehouse() class, but does not properly insert into the array i'm working on when creating an object of the ToolWarehouse() class using default constructor(even though my println debugging statements indicate it does):
public void readBSAFile() throws IOException,
FileNotFoundException
{
FileInputStream fstream2 = new FileInputStream(filename);
DataInputStream dstream2 = new DataInputStream(fstream2);
while (dstream2.available() > 0)
{
try
{
toolName = dstream2.readUTF();
id = dstream2.readInt();
quality = dstream2.readInt();
numInStock = dstream2.readInt();
price = dstream2.readDouble();
dstream2.close();
System.out.println(toolName);
System.out.println(id);
System.out.println(quality);
System.out.println(numInStock);
System.out.println(price);
//tools.insert(quality, toolName, id, numInStock, price);
}
catch (EOFException e)
{
System.out.println("End of file reached");
}
}
tools.insert(quality, toolName, id, numInStock, price);
}//end readBSAFile
Indeed, you have to make sure the object is initialized before attempting to use it. You put
ToolWarehouse tools;
as a class variable, and in the dialog method you could say
tools = new ToolWareHouse();
to create the object and start using it. But maybe a better way is to just initialize it as a class variable straight way. e.g write
ToolWarehouse tools = new ToolWareHouse();
at the top of the class. (So it's a class variable, and known throughout the whole class)
You didn't show us too much code, so it's hard to tell what the exact problem is. But as you said, you don't initialize your object, so you're bound to get a nullPointerException when trying to pass it on to another method & use it.
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);
I'm trying to replace setCharAt with something that can be used with a JLabel... I've been on oracle doc's looking for a solution. i don't know if I'm looking for the wrong thing or it just doesn't exists.. if it doesn't exists how could i work around that? i understand my naming convention is off and will be changing them as soon as possible...
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import javax.swing.*;
public class HangmanPanel extends JPanel {
static Boolean FOUND;
private static final long serialVersionUID = -5793357804828609325L;
public static String answerKey() {
//get random array element
String array[] = new String[10];
array[0] = "hamlet";
array[1] = "mysts of avalon";
array[2] = "the iliad";
array[3] = "tales from edger allan poe";
array[4] = "the children of hurin";
array[5] = "the red b" +
"+adge of courage";
array[6] = "of mice and men";
array[7] = "utopia";
array[8] = "chariots of the gods";
array[9] = "a brief history of time";
ArrayList<String> list = new ArrayList<String>(Arrays.asList(array));
Collections.shuffle(list);
String s = list.get(0);
return s;
}
public StringBuilder dashReplace(String s) {
//replace non-white space char with dashes and creates StringBuilder Object
String tW = s.replaceAll("\\S", "-");
System.out.print(tW + "\n");
StringBuilder AnswerKey = new StringBuilder(tW);
return AnswerKey;
}
public static int findAndReplace(String s, JLabel answerKey, String sc,
char ch) {
//find position of user input and replace
int pos = -1;
FOUND = false;
while(true){
pos = s.indexOf(sc, pos+1);
if(pos < 0){
break;
}else{
FOUND = true;
//setCharAt dosen't work for JLable
answerKey.setCharAt(pos, ch);
}
}
JLabel AnswerKey2 = new JLabel(answerKey.toString());
return pos;
}
public HangmanPanel(final String s){
this.setLayout(null);
JLabel heading = new JLabel("Welcome to the Hangman App");
JButton Button = new JButton("Ok");
//get input
JLabel tfLable = new JLabel("Please Enter a Letter:");
final JLabel AnswerKey = new JLabel(dashReplace(answerKey()).toString());
final JTextField text = new JTextField(10);
heading.setSize(200, 50);
tfLable.setSize(150, 50);
text.setSize(50, 30);
Button.setSize(60, 20);
AnswerKey.setSize(200, 100);
heading.setLocation(300, 10);
tfLable.setLocation(50, 40);
text.setLocation(50, 80);
Button.setLocation(100, 85);
AnswerKey.setLocation(100,85);
this.add(heading);
this.add(tfLable);
this.add(text);
this.add(Button);
this.add(AnswerKey);
Button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// can't access text
String sc = text.getText();
char ch = sc.charAt(0);
findAndReplace(s, AnswerKey, sc, ch);
}
});
}
}
Why are you trying to use setCharAt(...) with a JLabel. A label is meant to display static text. The only way to change it is to replace the entire string.
I guess you could do something like:
StringBuilder text = label.getText();
text.setCharAt(...);
label.setText( text.toString() );
Another option would be to use a JTextField that looks like a JLabel:
JTextField label = new JTextField(...);
label.setEditable(false);
label.setBorder(null);
label.setOpaque(false);
Then when you need to change the text you could do:
label.select(...);
label.replaceSelection(...);
The only method available for setting text for JLabel components is setText. Also Strings are immutable. Therefore, you can use StringBuilder:
StringBuilder builder = new StringBuilder(answerKey.getText());
builder.setCharAt(pos, ch);
answerKey.setText(builder.toString());
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.