I'm new to JFrame, and I wanted to know why my JOptionPane won't stop popping up. When I type into the JOptionPane continuously, the values keep overlapping on the JFrame overtop of the previous ones, and it's keeping my program in a loop, preventing the printing process from opening up. I think it's because the program requests input values in a public void class rather than a public static void main class, but I don't know how to put these values on a JFrame otherwise because of the graphics component.
import java.awt.*;
import java.awt.print.PageFormat;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import javax.swing.*;
public class Assignment3 extends JFrame
{
Assignment3()
{
setTitle("Amber's Skateboarders");
setSize(1200,720);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public void paint(Graphics g)
{
Font bigName = new Font("Ariel Bold", Font.BOLD, 20);
Font company = new Font("Comic Sans", Font.BOLD, 12);
Font myList = new Font("Comic Sans", Font.PLAIN, 12);
g.setFont(bigName);
g.drawString("Skateboarders", 15, 100);
String companyName;
String companyAddress;
int itemIndex = 0;
int pricesIndex = 0;
int quantityIndex = 0;
String[] merchandise = new String[1000];
double[] prices = new double[1000];
int[] quantity = new int[1000];
int addMore;
String[] options = {"Yes", "No"};
double subtotal = 0;
double[] result = new double[1000];
String[] list = new String[1000];
companyName = JOptionPane.showInputDialog(null, "What is your company name?");
g.setFont(company);
g.drawString(companyName, 15, 115);
companyAddress = JOptionPane.showInputDialog(null, "What is your company's address?");
g.setFont(company);
g.drawString(companyAddress, 15, 130);
do
{
merchandise[itemIndex] = JOptionPane.showInputDialog(null, "What is the name of the item you want?");
prices[pricesIndex] = Double.parseDouble(JOptionPane.showInputDialog(null, "How much does this cost?"));
quantity[quantityIndex] = Integer.parseInt(JOptionPane.showInputDialog(null, "How much of this item do you need?"));
itemIndex++;
pricesIndex++;
quantityIndex++;
addMore = JOptionPane.showOptionDialog(null, "Do you want to add more to your shopping cart?", "Before you go!", JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE,null, options, options[0]);
}
while(addMore == 0);
int k;
g.setFont(myList);
if (addMore == 1)
{
for (int i = 0; i <= pricesIndex-1; i++)
{
result[i] = prices[i]*quantity[i];
}
for (double j : result)
{
subtotal += j;
}
for (k = 0; k<pricesIndex; k++)
{
list[k] = String.valueOf(quantity[k])+"\u00D7"+merchandise[k];
g.drawString(list[k], 15, k*15+145);
g.drawString("$" +String.valueOf(result[k]), 120, k*15+145);
//all += String.valueOf(quantity[k])+"\u00D7"+merchandise[k]+"\t\t\t"+String.valueOf(result[k])+"\n";
}
k=pricesIndex;
double taxes = subtotal*0.2;
g.setFont(company);
g.drawString("Subtotal: ", 15, k*15+145);
g.drawString("$"+String.valueOf(subtotal), 120, k*15+145);
k++;
g.drawString("Tax: ", 15, k*15+145);
g.drawString("$"+String.valueOf(taxes), 120, k*15+145);
k++;
g.drawString("Total: $", 15, k*15+145);
g.drawString("$"+String.valueOf(taxes+subtotal), 120, k*15+145);
}
public static void main(String[] args)
{
Assignment3 main = new Assignment3();
main.paint(null);
}
}
I think your problem in next:
1) You invoke your JOptionPane inside paint() method, it is'n proper way.
2) Why you draw your items with Graphics, I think you can use JLabel's or JTextField's as recommended by #trashgod. I recommend you to use JTable, i think it is suitable for your case. read tutorial for that.
3) You can add new items with help of button action(tutorial for button) instead of while looping.
4) If you want actually to draw your data on component. Extend JPanel class, add instance of it to your JFrame and paint in paintComponents(Graphics g) method.
As discussed in Painting in AWT and Swing: The Paint Methods, "Swing programs should override paintComponent() instead of overriding paint()." It's also highly unusual to evoke a dialog in a callback that is not under you control. Since you're mostly calling drawString() you may find it easier to simply update components such as JLabel and JTextField via setText(). If you want to update the drawing area automatically, use a modeless dialog, shown here.
Related
I have to create an interface which allows the user to increase/decrease the size of a piece of text and to show the current font size value of that text.
I have two buttons, increase and decrease.
I have two labels. One label has the text "X" which needs to change size every time a button is pressed. The other label has to display the current font size value of "X".
I have managed to implement the increase/decrease method for the text, however I cannot get the value of the text to increase after clicking. The value of the text when increased only allows the user to increase it once. I want the program to be able to increase it by 5 every time the button is activated.
I believe I have to somehow store the new value of the font size and use the new value to allow me to increase/decrease even more.
If anyone could tell me how to do this, or show a solution, it would be greatly appreciated.
package lab3;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class FontSize extends JFrame{
JButton increase, decrease;
JLabel sizeX, sizeValue;
public static void main (String[]args){
FontSize changeFont = new FontSize();
changeFont.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
changeFont.setTitle("Increase/Decrease Font Size");
changeFont.setSize(900,700);
changeFont.setVisible(true);
changeFont.setLayout(new GridLayout(2,2));
}
public FontSize(){
increase = new JButton("increase");
increase.setBackground(Color.white);
increase.setFont(increase.getFont().deriveFont(30.0f));
add(increase);
decrease = new JButton("decrease");
decrease.setBackground(Color.white);
decrease.setFont(decrease.getFont().deriveFont(30.0f));
add(decrease);
sizeX = new JLabel("X", SwingConstants.CENTER);
sizeX.setBackground(Color.yellow);
sizeX.setFont(sizeX.getFont().deriveFont(30.0f));
add(sizeX);
int temp = sizeX.getFont().getSize();
sizeValue = new JLabel("",SwingConstants.CENTER);
sizeValue.setText(String.valueOf(temp));
sizeValue.setBackground(Color.yellow);
sizeValue.setFont(sizeValue.getFont().deriveFont(30.0f));
add(sizeValue);
event e = new event();
increase.addActionListener(e);
decrease.addActionListener(e);
}
public class event implements ActionListener {
public void actionPerformed(ActionEvent e){
String operation = e.getActionCommand();
int temp = sizeX.getFont().getSize();
int temp2 = sizeValue.getFont().getSize();
if(operation.equals("increase"))
{
temp = temp + 5;
sizeX.setFont(new Font("Arial", Font.PLAIN, temp));
temp2 = temp2 + 5;
sizeValue.setText(String.valueOf(temp2));
}
else if(operation.equals("decrease"))
{
temp = temp - 5;
sizeX.setFont(new Font("Arial", Font.PLAIN, temp));
temp2 = temp2 - 5;
sizeValue.setText(String.valueOf(temp2));
}
}
}
}
Simple fix really: on like 64 of the original code, you accidentaly are trying to count the variable temp2 as the size of the font of it, not the actual text. I've attached a slightly refactored, as well as corrected, version of the code.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class FontSize extends JFrame implements ActionListener {
private JButton increase, decrease;
private JLabel sizeX, sizeValue;
public static void main (String[]args) {
FontSize changeFont = new FontSize();
changeFont.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
changeFont.setTitle("Increase/Decrease Font Size");
changeFont.setSize(900,700);
changeFont.setVisible(true);
changeFont.setLayout(new GridLayout(2,2));
}
public FontSize(){
increase = new JButton("increase");
increase.setBackground(Color.white);
increase.setFont(increase.getFont().deriveFont(30.0f));
add(increase);
decrease = new JButton("decrease");
decrease.setBackground(Color.white);
decrease.setFont(decrease.getFont().deriveFont(30.0f));
add(decrease);
sizeX = new JLabel("X", SwingConstants.CENTER);
sizeX.setBackground(Color.yellow);
sizeX.setFont(sizeX.getFont().deriveFont(30.0f));
add(sizeX);
int temp = sizeX.getFont().getSize();
sizeValue = new JLabel("",SwingConstants.CENTER);
sizeValue.setText(String.valueOf(temp));
sizeValue.setBackground(Color.yellow);
sizeValue.setFont(sizeValue.getFont().deriveFont(30.0f));
add(sizeValue);
increase.addActionListener(this);
decrease.addActionListener(this);
}
public void actionPerformed(ActionEvent e) {
String operation = e.getActionCommand();
int temp = sizeX.getFont().getSize();
int temp2 = Integer.parseInt(sizeValue.getText());
if(operation.equals("increase")) {
temp += 5;
sizeX.setFont(new Font("Arial", Font.PLAIN, temp));
temp2 += 5;
sizeValue.setText(String.valueOf(temp2));
} else if(operation.equals("decrease")) {
temp -= 5;
sizeX.setFont(new Font("Arial", Font.PLAIN, temp));
temp2 -= 5;
sizeValue.setText(String.valueOf(temp2));
}
}
}
Hope this helped, and best of luck to you.
int temp2 = sizeValue.getFont().getSize(); isn't the size of the font you're changing, but is the size of the font which is been used to render the label.
Try using something more like instead...
String operation = e.getActionCommand();
int temp = sizeX.getFont().getSize();
if (operation.equals("increase")) {
temp = temp + 5;
sizeX.setFont(new Font("Arial", Font.PLAIN, temp));
sizeValue.setText(String.valueOf(temp));
} else if (operation.equals("decrease")) {
temp = temp - 5;
sizeX.setFont(new Font("Arial", Font.PLAIN, temp));
sizeValue.setText(String.valueOf(temp));
}
You may also need to call revalidate(); and repaint(); at the end of the actionPerformed method to force a refresh, but it work okay without for me
Equally, you could just something like...
Font font = sizeX.getFont();
if (operation.equals("increase")) {
font = font.deriveFont(font.getSize() + 5f);
} else if (operation.equals("decrease")) {
font = font.deriveFont(font.getSize() - 5f);
}
sizeX.setFont(font);
sizeValue.setText(NumberFormat.getNumberInstance().format(font.getSize()));
Which allows you to maintain the font that the label was originally using, but increases/decreases it's size, but also relies on the actual Font size to update the display, rather the relying on calculated values...
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);
This program is designed to take a shape decided by the user and change the size of it based on input.
I have two issues. One is that the user will have to input it as a string yet the size value is an integer. If I convert integer to string it will give me an null exception when converting. (java.lang.Integer.parseInt(Unknown Source)Exception).)
The other problem is that I do not know what to add in the actionPerfomed method. Since all of the information only needs to go to the paint method. How can I transfer the integer value into the Paint method.
import java.io.*;
import java.util.*;
import java.text.*;
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import java.applet.Applet;
public class ChangeSize extends Applet
implements ActionListener
{
Button bttn1 = new Button ("Circle");
Button bttn2 = new Button ("Square");
Button bttn3 = new Button ("Triangle");
Button bttn4 = new Button ("Rectangle");
Label lab1; // text within applet
TextField t1; // where user inputs text
String input;
int choice;
public void init ()
{
this.setSize (500, 300);
setBackground (Color.lightGray);
lab1 = new Label ("Insert the size of the shape:");
//int Size = Integer.parseInt (input);
add (lab1);
t1 = new TextField ();
add (t1);
bttn1.addActionListener (this); // circle button
bttn2.addActionListener (this); // square button
bttn3.addActionListener (this); // triangle button
bttn4.addActionListener (this); // rectangle button
add (bttn1);
add (bttn2);
add (bttn3);
add (bttn4);
}
public void paint (Graphics g)
{
int xpoints[] = {25, 145, 25, 145, 25}; \
int ypoints[] = {25, 25, 145, 145, 25};
int npoints = 5;
switch (choice)
{
case 1:
if (choice == 1)
g.setColor (Color.red);
g.fillOval (30, 40, 20, 20); // I want it to be (30,40, 20, size). Instead
case 2:
if (choice == 2)
g.fillRect (20, 40, 100, 100);
case 3:
if (choice == 3)
g.fillPolygon (xpoints, ypoints, npoints);
case 4:
if (choice == 4)
g.fillRect (20, 40, 50, 100);
break;
}
showStatus ("Please seclect an option.");
}
public void actionPerformed (ActionEvent evt)
{
if (evt.getSource () == bttn1)
choice = 1;
else if (evt.getSource () == bttn2)
choice = 2;
else if (evt.getSource () == bttn3)
choice = 3;
else if (evt.getSource () == bttn4)
choice = 4;
Size = t1.getText ();
// I dont know what to put here
repaint ();
}
}
You're close to a solution and your comment, // I want it to be (30,40, 20, size). Instead
holds the key.
Give your application an int class field or fields to hold your drawing size.
use that size to set the shape's size in your painting routine.
Allow the user to change the sizes in the actionPerformed method.
The text you get will be a String, and you will need to parse this into an int before you can use it via the Integer.parseInt(...) method.
Regarding:
I have two issues. One is that the user will have to input it as a string yet the size value is an integer. If I convert integer to string it will give me an null exception when converting. (java.lang.Integer.parseInt(Unknown Source)Exception).)
The problem is where you're trying to parse the int. You're doing it in the init method which is the method that creates and builds the applet, which is way before the user has had time to add input into the text field. It would be much better to parse in the actionPerformed method.
I trying to make a math quiz game that generates random question and keep track of of what question are wrong and write.
I trying to figure out how to make my program respond if the answer written in the text field is correct or incorrect when I click the JButton `answerbutton`. I'm very new to using `ActionListener`.
ok so i got action listener to work but when i type in a answer it say my answeris wrong, even though it right. the first question that appear work fine but after that it , it say all my answer are wrong and it still wont keep track of my score.
import java.util.Scanner;
import javax.swing.*;
import javax.swing.border.TitledBorder;
import java.util.Random;
import java.util.Scanner;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class PracticeMath extends JFrame {
Scanner k = new Scanner(System.in);
Random generator = new Random();
protected JButton excerciseButton = new JButton( "New Excerices" ); // start new quiz session
protected JButton answerButton = new JButton( "Answer" ); // set new question, check if the answer correct or wrong
protected JLabel titlelabel = new JLabel( "How much is: " );
protected int correctcounter = 0; // keep track of correct answer
protected int wrongcounter = 0; // keep track of wrong answer
protected int one = generator.nextInt(10);//generate ranodm first number of question
protected int two = generator.nextInt(10); // generate random second number of question
protected int i = generator.nextInt(4); // generate random operator
protected char[] ops = { '+', '-', '/', '*' }; // the math operator
protected JLabel correctlabel = new JLabel(" Number of Correct Answer: ");
protected JLabel wronglabel = new JLabel( " Number of Wrong answers: " );
protected JLabel firstnum = new JLabel("" + one); // display first number
protected JLabel secondnum = new JLabel("" + two); // display second number
protected JLabel randomOP = new JLabel("" + ops[i]); display operator
protected JLabel equalOP = new JLabel("=");
protected JTextField answerText = new JTextField(); //text area for writing you answer
protected JLabel questionmark = new JLabel("?");
protected JLabel correct = new JLabel(""+ correctcounter); // display correct answer
protected JLabel wrong = new JLabel(""+ wrongcounter); // display wrong answer
protected JLabel commentlabel = new JLabel(""); // set a comment for how good you doing. optionial
public PracticeMath(){
answerText.setColumns(5);
JPanel Panel1 = new JPanel();// add a panel
FlowLayout flowLayout = (FlowLayout) Panel1.getLayout();// layout for panel
getContentPane().setLayout( new FlowLayout( FlowLayout.LEFT, 5, 5)); // set layout
getContentPane().add(Panel1); // set panel
titlelabel.setForeground(Color.ORANGE);
titlelabel.setFont(new Font("Tahoma", Font.PLAIN, 25));
Panel1.add(titlelabel);
firstnum.setFont(new Font("Tahoma", Font.PLAIN, 20));
Panel1.add(firstnum);
randomOP.setFont(new Font("Tahoma", Font.PLAIN, 25));
Panel1.add(randomOP);
secondnum.setFont(new Font("Tahoma", Font.PLAIN, 20));
Panel1.add(secondnum);
equalOP.setFont(new Font("Tahoma", Font.PLAIN, 20));
Panel1.add(equalOP);
Panel1.add(answerText);
questionmark.setFont(new Font("Tahoma", Font.PLAIN, 20));
Panel1.add(questionmark);
Panel1.add(commentlabel);
JPanel Panel3 = new JPanel();
FlowLayout flowLayout3 = (FlowLayout) Panel3.getLayout();
flowLayout3.setHgap(15);
getContentPane().setLayout( new FlowLayout( FlowLayout.LEFT, 5, 5));
getContentPane().add(Panel3);
Panel3.add(excerciseButton);
Panel3.add(answerButton);
JPanel panel2 = new JPanel();
panel2.setBorder(new TitledBorder("Statistic"));
getContentPane().add(panel2);
panel2.setLayout(new GridLayout(0, 2, 0, 0));
panel2.add(correctlabel);
panel2.add(wronglabel);
correct.setForeground(Color.GREEN);
correct.setFont(new Font("Tahoma", Font.PLAIN, 25));
panel2.add(correct);
wrong.setForeground(Color.RED);
wrong.setFont(new Font("Tahoma", Font.PLAIN, 25));
panel2.add(wrong);
answerButton.addActionListener( this );
}
public static void main(String[] args) {
PracticeMath frame = new PracticeMath();
frame.pack();
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400,400);
frame.setTitle( "Math Practice");
frame.setVisible(true);
}
public void actionPerformed( ActionEvent ae )
{
String answer = answerText.getText();
int answerint = Integer.parseInt(answer);
if(one + two == answerint){
correctcounter++;
System.out.println("correct");
firstnum.setText("" + generator.nextInt(11));
randomOP.setText("" + ops[generator.nextInt(4)]);
secondnum.setText("" + generator.nextInt(11));
}
else if(one-two == answerint){
correctcounter++;
System.out.println("correct");
firstnum.setText("" + generator.nextInt(11));
randomOP.setText("" + ops[generator.nextInt(4)]);
secondnum.setText("" + generator.nextInt(11));
}
else if(one * two ==answerint){
correctcounter++;
System.out.println("correct");
firstnum.setText("" + generator.nextInt(11));
randomOP.setText("" + ops[generator.nextInt(4)]);
secondnum.setText("" + generator.nextInt(11));
}else if(one/two == answerint){
correctcounter++;
System.out.println("correct");
firstnum.setText("" + generator.nextInt(11));
randomOP.setText("" + ops[generator.nextInt(4)]);
secondnum.setText("" + generator.nextInt(11));
}
else{
wrongcounter++;
System.out.println("wrong");
firstnum.setText("" + generator.nextInt(11));
randomOP.setText("" + ops[generator.nextInt(4)]);
secondnum.setText("" + generator.nextInt(11));
}
}
}
In order to make your buttons do some desired action, like you say, you will need to use an ActionListener. To do this, you will want to define some class that implements the ActionListener interface. This class can be your PracticeMath class, if you want it to be. So do this:
public class PracticeMath extends JFrame implements ActionListener
{...}
When you do this, your PracticeMath class will be responsible for specifying a definition to any methods that are part of the ActionListener interface; in this case
public void actionPerformed( ActionEvent ae )
{
// put something intelligent here
}
You then need to add this ActionListener to whichever buttons you want it to listen to. Namely
answerButton.addActionListener( this );
Use "this" as the argument since your ActionListener is your PracticeMath class. Now, when you press the answer button, whatever code you put into your actionPerformed(...) method will be called. So you can evaluate your answer within.
Update to reflect the comment below:
Here is what your code should look like for the actionPerformed method.
public void actionPerformed( ActionEvent ae )
{
String answer = answerText.getText();
int answerint = Integer.parseInt(answer);
if(one + two == answerint){
correctcounter++;
System.out.println("correct");
one = generator.nextInt(11);
two = generator.nextInt(11);
// I don't know if you actually store the operator anywhere
operator = ops[generator.nextInt(4)];
firstnum.setText("" + one);
randomOP.setText("" + operator);
secondnum.setText("" + two);
}
else if(one-two == answerint){
// ... and do the same for the other cases too
This, ofcourse, does not address the fact that you are not checking to see if the correct operator was actually used, but this should fix the problem with every answer past the first one being labeled as incorrect.
I am writing a Mortgage Calculator for class and I have it working the way I need it to, except everytime I click the "Calculate" button it will just continue to add to the table instead of the table clearing and showing new values. I know my code might look a little sloppy and I have some things commented out that don't need to be there because I'm still working it, but do you have any suggestions?
FYI I am still a beginner learning Java and it has taken me over 20hrs to get this far (and i"m pretty proud of myself!) Thank you!!
//Import all required Packages
import javax.swing.*;
import javax.swing.table.*;
import java.awt.*;
import java.text.*;
import java.awt.event.*;
public class MortgageCalculator extends JFrame implements ActionListener {
// Loan Values
double intPrincipal, interestRate, calcPayment, monthlyInterest, currentInterest, principalPaid, newBalance;
int totalMonths;
double[] loanInterest = {5.35, 5.5, 5.75}; // Yearly interest in decimal form
int[] loanTerm = {7, 15, 30}; // Total months of term
String principal;
String comboArray[] = {"7 Years at 5.35%", "15 Years at 5.5%", "30 Years at 5.75%"};
int termYears, termMonths, done, i=0, m=0, p=0;
//Set up panels
JPanel contentPanel;
//Set up labels
JLabel mortgageLabel, paymentLabel, termLabel;
//Set up buttons
JButton calculateButton, clearButton, exitButton;
//TextFields
JTextField txtMortgage = new JTextField(10);
JTextField txtPayment = new JTextField(10);
//New Text Area
JTextArea textarea = new JTextArea();
DecimalFormat df = new DecimalFormat("$###,###.00"); //Formatting the results to decimal form
//Combo Box
JComboBox loansList = new JComboBox();
DefaultTableModel model = new DefaultTableModel();
JTable table = new JTable(model);
//Build GUI
public MortgageCalculator()
{
super();
initializeContent();
}
public void initializeContent()
{
this.setSize(700, 500);
this.setLocation(0, 0);
this.setContentPane(contentPanel());
this.setTitle("Mortgage Calculator");
}
public JPanel contentPanel()
{
contentPanel = new JPanel();
contentPanel.setLayout(null);
//Add labels to the panel
mortgageLabel = new JLabel("Mortgage:");
mortgageLabel.setLocation(200, 30);
mortgageLabel.setSize(100, 25);
contentPanel.add(mortgageLabel);
termLabel = new JLabel("Term & Rate:");
termLabel.setLocation(183, 55);
termLabel.setSize(100, 30);
contentPanel.add(termLabel);
paymentLabel = new JLabel("Monthly Payment:");
paymentLabel.setLocation(158, 85);
paymentLabel.setSize(100, 30);
contentPanel.add(paymentLabel);
//Text Fields
txtMortgage = new JTextField(10);
txtMortgage.setLocation(280, 30);
txtMortgage.setSize(150, 25);
contentPanel.add(txtMortgage);
txtPayment = new JTextField(10);
txtPayment.setLocation(280, 85);
txtPayment.setSize(150, 25);
contentPanel.add(txtPayment);
//Combo Box
loansList.addItem(comboArray[0]);
loansList.addItem(comboArray[1]);
loansList.addItem(comboArray[2]);
loansList.setLocation(280, 55);
loansList.setSize(150, 25);
loansList.addActionListener(this);
contentPanel.add(loansList);
//textarea.setPreferredSize(new Dimension(650, 300));
//JScrollPane scroller = new JScrollPane(textarea);
JScrollPane scroller = new JScrollPane(table);
contentPanel.add(scroller);
scroller.setSize(650,300);
scroller.setLocation(20, 150);
textarea.setLineWrap(true);
model.addColumn("Payment Number");
model.addColumn("Current Interest");
model.addColumn("Principal Paid");
model.addColumn("New Balance");
//Buttons
exitButton = new JButton("Exit");
exitButton.setLocation(450, 30);
exitButton.setSize(100, 25);
contentPanel.add(exitButton);
clearButton = new JButton("Clear");
clearButton.setLocation(450, 55);
clearButton.setSize(100, 25);
contentPanel.add(clearButton);
calculateButton = new JButton("Calculate");
calculateButton.setLocation(450, 85);
calculateButton.setSize(100, 25);
contentPanel.add(calculateButton);
//setup up buttons
calculateButton.addActionListener(this);
clearButton.addActionListener(this);
exitButton.addActionListener(this);
return contentPanel;
}
//Define actions performed for buttons
public void actionPerformed(ActionEvent e)
{
String arg = e.getActionCommand();
if (e.getSource() == loansList) {
switch (loansList.getSelectedIndex()) {
case 0:
i = 0;
break;
case 1:
i = 1;
break;
case 2:
i = 2;
break;
}
}
if (arg == "Calculate")
{
txtPayment.setText("");
principal = txtMortgage.getText();
try {
intPrincipal = Double.parseDouble(principal);
if (intPrincipal <= 0) throw new NumberFormatException();
}
catch(NumberFormatException n){
txtPayment.setText("Please Enter a Postive Numeric Number");
done = 1;
}
if (done == 1)
done = 0;
else {
interestRate = loanInterest[i];
termYears = loanTerm[i];
monthlyInterest = interestRate/(12*100); //calculates monthly interest
termMonths = termYears*12; //calculates term length in months
calcPayment = monthlyInterest*intPrincipal/(1-Math.pow((1+monthlyInterest), -termMonths)); //calculates monthly payment
txtPayment.setText(" " + df.format(calcPayment));
for (m=0; m<=totalMonths; m++) {
totalMonths = loanTerm[i]*12;
currentInterest = intPrincipal * monthlyInterest;
principalPaid = calcPayment - currentInterest;
newBalance = intPrincipal - principalPaid;
intPrincipal = newBalance;
/* printAndAppend(
(m+1) + " " +
df.format(currentInterest) + " " +
df.format(principalPaid) + " " +
df.format(newBalance) + "\n");
//textarea.setText(df.format(currentInterest));
if(intPrincipal <= 1){ break;}*/
// Create a couple of columns
model.addRow(new Object[]{m+1, df.format(currentInterest), df.format(principalPaid), df.format(newBalance)});
if(intPrincipal <= 1){ break;}
}
}
}
else if (e.getSource() == clearButton)
{
txtMortgage.setText(""); //clear Mortgage textfield
txtPayment.setText(""); //clear Payment textfield
txtMortgage.requestFocusInWindow(); //move cursor back to Mortgage textfield
loansList.setSelectedIndex(0);
}
else if (e.getSource() == exitButton)
System.exit(0);
}
public void printAndAppend(String text) {
textarea.append(text);
}
public static void main(String[] args)
{
new MortgageCalculator().setVisible(true);
}
}
To clear all you need to do is set the row count of the model to 0 -- that's it:
else if (e.getSource() == clearButton) {
txtMortgage.setText("");
txtPayment.setText("");
txtMortgage.requestFocusInWindow();
loansList.setSelectedIndex(0);
model.setRowCount(0); //!! added
}
Also, this is not good:
if (arg == "Calculate") {
As you shouldn't use == to compare Strings. If you want to compare Strings, use the equals method:
if (arg.equals("Calculate")) {
or the equalsIgnoreCase method:
if (arg.equalsIgnoreCase("Calculate")) {
The reason this is important is because == checks to see if one String object is the same as another String object, and you really don't care about this. Instead you want to know if one String holds the same chars as another, and that's what equals tests for.
Also, I'd set the model's row count to 0 at the beginning of your calculate method, and this way you can recalculate things without having to clear.