How to calculate number from two Jtextfield? - java

I'm designing a food ordering system which I need to get the input of cash that customer paid, then minus with the total price they need to pay to calculate the change. My JTextField can't show the correct answer for the change, it only show 0.0. I'm not sure what's the problem with my code. Hope that you all can help me. Appreciate your helps, thank you!
public Cash() {
init();
btnPay.addActionListener(this);
setVisible(true);
}
public String returnChange1() {
double change = 0.00 ;
double custPay;
String total = lblDisplayTotal.getText();
double a=Double.parseDouble(total);
if (!(txtCustPay.getText().isEmpty())){
custPay = Double.parseDouble(txtCustPay.getText());
change = custPay - a;
}
return String.valueOf(change);
}
public void actionPerformed(ActionEvent e) {
if (e.getSource().equals(btnPay)) {
returnChange1();
}
}
public void init() {
txtChange = new JTextField(returnChange1());
txtChange.setSize(150, 30);
txtChange.setLocation(150, 250);
add(txtChange);
}

You are not assigning the function to the text field. In the button action, don't simply call the function, in this case what you should do is assign the function to the text field: txtChange.setText(returnChange1()), Also try to put a try and catch where you convert the text to double:
try{
double a = Double.parseDouble(total);
}catch(NumberFormatException e){
e.printStackTrace;
}
The above code is useful when the user mistakenly enters a character that is not a number.
public Cash() {
init();
btnPay.addActionListener(this);
setVisible(true);
}
public String returnChange1() {
double change = 0.00;
double custPay;
String total = lblDisplayTotal.getText();
double a = Double.parseDouble(total);
if (!(txtCustPay.getText().isEmpty())) {
custPay = Double.parseDouble(txtCustPay.getText());
change = custPay - a;
}
return String.valueOf(change);
}
public void actionPerformed(ActionEvent e) {
if (e.getSource().equals(btnPay)) {
txtChange.setText(returnChange1());
}
}
public void init() {
txtChange = new JTextField(returnChange1());
txtChange.setSize(150, 30);
txtChange.setLocation(150, 250);
add(txtChange);
}

Related

How to trigger event based on invalid manual edit of text field in a jSpinner outside min/max range

I have a java swing UI jSpinner component which accepts double values and has a minimum and maximum allowable ranges set. The issue is that when the user manually enters a value in the jFormattedTextField part of the component which is outside of the min / max range and the focus leaves the text field the value is immediately rejected and reverted the the last previous valid value, (which is the expected and correct behavior for the component).
The user has requested that the behavior be changed such that when an invalid value is entered and the focus leaves the text field instead of just reverting to the last valid value it should be reverting to the maximum or minimum valid value depending on if the user entered an invalid value which was either greater than the maximum allowable or less than the allowable minimum.
For example if the spinner's minimum / maximum ranges are set to (1,10) and the user manually enters a value of 20 then the text field should bet set to 10, not the last valid value which was present in the jSpinner's model.
I have tried quite a few different ways to resolve this issue including at attaching a KeyListener to the the underlying JFormattedTextField as well as a PropertyChangeListener to the Jspinner's Number/Default editor but it seems like the main issue is that I am unable to get the invalid value's actual value so that I can determine if it is outside the range either above the max or below the min.
Using a KeyListener (Which i realize is NOT the appropriate way to handle the input of a JFormattedTextField) I am able to at least catch the key strokes but with the following code the most I am able to do is catch an exception which lets me know that the input value is outside the min/max range and nothing more.
In the code example the value I am receiving is as the 'dirtyValue' is always the last valid value and never the actual invalid newly entered user input.
I am totally out of ideas. Can anyone help provide some insight?
I have tried using a KeyListener, a propertyChangeListener and an DocumentListener.
private JFormattedTextField tf = ((JSpinner.NumberEditor)
jSpinnerTiming.getEditor()).getTextField();
((JSpinner.DefaultEditor)jSpinnerTiming.getEditor()).getTextField().
addKeyListener(new KeyListener(){
#Override public void keyPressed(KeyEvent e) {
}
#Override public void keyReleased(KeyEvent e) {
}
#Override public void keyTyped(KeyEvent e) {
try { tf.commitEdit(); } catch
(ParseException e1) { // TODO Auto-generated catch block
e1.printStackTrace(); }
double dirtyValue = (double)tf.getValue();
double max = ALLOWABLE_MAX;
double min = ALLOWABLE_MIN;
if (dirtyValue > max) {
jSpinnerTiming.setValue(max);
; } else if(dirtyValue < min){
jSpinnerTiming.setValue(min);
} }
});
Here is a solution I was able to get working using a FocusListener, although I am not sure how correct it is.
private JFormattedTextField tf = ((JSpinner.DefaultEditor) jSpinnerTiming.getEditor()).getTextField();
((JSpinner.DefaultEditor)jSpinnerTiming.getEditor()).getTextField().addFocusListener(new FocusListener() {
#Override
public void focusLost(FocusEvent e) {
// The unchecked user input value
double dirtyValue = Double.parseDouble(tf.getText());
// Get Minimum and Maximum values from jSpinner's Model
double max = (Double) ((SpinnerNumberModel) jSpinnerTiming.getModel()).getMaximum();//MAX_ALLOWED_RATE
double min = (Double) ((SpinnerNumberModel) jSpinnerTiming.getModel()).getMinimum();//LOWEST_ALLOWABLE_RATE;
if (dirtyValue > max) {
jSpinnerTiming.setValue(max);
} else if(dirtyValue < min){
jSpinnerTiming.setValue(min);
}
}
#Override
public void focusGained(FocusEvent e) {
// TODO Auto-generated method stub
}
});
The problem is that JSpinner keeps everything internal. The editor installs an AbstractFormatter which never allows below the minimum or above the maximum, so you never get a chance to react to those conditions.
Since it’s nearly impossible to intercept an existing AbstractFormatter’s behavior, I would just create the JSpinner with no minimum or maximum, and enforce those bounds manually in a ChangeListener:
private static JSpinner createSpinner() {
double initialValue = 20;
SpinnerModel model =
new SpinnerNumberModel(initialValue, null, null, 1d);
model.addChangeListener(e -> {
double value = ((Number) model.getValue()).doubleValue();
if (value < ALLOWABLE_MIN) {
EventQueue.invokeLater(() -> model.setValue(ALLOWABLE_MIN));
} else if (value > ALLOWABLE_MAX) {
EventQueue.invokeLater(() -> model.setValue(ALLOWABLE_MAX));
}
});
return new JSpinner(model);
}
You can also change the AbstractFormatter of the JFormattedTextField of the DefaultEditor of the JSpinner (via a custom AbstractFormatterFactory), like the following code:
import java.awt.Dimension;
import java.text.ParseException;
import java.util.Objects;
import javax.swing.JButton;
import javax.swing.JFormattedTextField;
import javax.swing.JFormattedTextField.AbstractFormatter;
import javax.swing.JFormattedTextField.AbstractFormatterFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.JSpinner.DefaultEditor;
import javax.swing.SpinnerNumberModel;
public class Main {
public static class IntegerFormatter extends AbstractFormatter {
private final int min, max;
public IntegerFormatter(final int min, final int max) {
this.min = min;
this.max = max;
}
#Override
public Object stringToValue(final String text) throws ParseException {
try {
//This is where we compare for out of bounds values:
final int val = Integer.parseInt(text);
if (val < min)
return min;
if (val > max)
return max;
return val;
}
catch (final NumberFormatException nfx) {
//Find where in the string is the parsing error (so as to return ParseException accordingly).
int i = 0;
for (final int cp: text.codePoints().toArray()) {
if (!Character.isDigit(cp))
throw new ParseException("Not a digit.", i);
++i;
}
//Should not happen:
throw new ParseException("Failed to parse input \"" + text + "\".", 0);
}
}
#Override
public String valueToString(final Object value) throws ParseException {
return Objects.toString(value);
}
}
public static class IntegerFormatterFactory extends AbstractFormatterFactory {
private final int min, max;
public IntegerFormatterFactory(final int min, final int max) {
this.min = min;
this.max = max;
}
#Override
public AbstractFormatter getFormatter(final JFormattedTextField tf) {
if (!(tf.getFormatter() instanceof IntegerFormatter))
return new IntegerFormatter(min, max);
return tf.getFormatter();
}
}
public static void main(final String[] args) {
final SpinnerNumberModel model = new SpinnerNumberModel(0, -10, 10, 1);
final JSpinner spin = new JSpinner(model);
spin.setPreferredSize(new Dimension(100, 25));
((DefaultEditor) spin.getEditor()).getTextField().setFormatterFactory(
new IntegerFormatterFactory((Integer) model.getMinimum(), (Integer) model.getMaximum())
);
final JPanel contents = new JPanel(); //FlowLayout.
contents.add(spin);
contents.add(new JButton("Click me to change focus!"));
final JFrame frame = new JFrame("Spinner out of bounds");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(contents);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}

JAVA - Trying to use a variable from inside an actionperformed outside the class

I am trying to access the (double) percentage variable outside my actionPerformed while retaining the changes that it goes through.
it is a drop down menu, and an ok button you press. once you press it, it calculates a value for percentage, which then i want to use later on in the program.
Here is a snippet of the code:
btn.addActionListener(
new ActionListener(){
public void actionPerformed(ActionEvent e){
String currentCountry = (String)cb.getSelectedItem();
double percentage = 0.00;
if(currentCountry.equals("Brazil") || currentCountry.equals("Argentina")) {
cb2.removeAllItems();
for(int i = 0; i < choicesSouthAmerica.length; i++) {
cb2.addItem(choicesSouthAmerica[i]);
}
}
else {
cb2.removeAllItems();
for(int i = 0; i < choicesEurope.length; i++) {
cb2.addItem(choicesEurope[i]);
}
}
btn.setEnabled(false);
btn2.setEnabled(true);
if(currentCountry.equals("Brazil") || currentCountry.equals("Argentina")){
percentage = 1/5;
System.out.println(percentage);
}
else{
percentage = 1/8;
System.out.println(percentage);
}
}
}
);
Thank you kindly
you could use the putClientProperty(Object,Object) and getClientProperty(Object) functions as follow :
JButton btn = new JButton("Ok");
btn.putClientProperty("percentage",1.0);//or whatever initial value
btn.addActionListener(arg0 -> {
JButton source = (JButton) arg0.getSource();
double per = (double)source.getClientProperty("percentage");
per = (double)10/8;
source.putClientProperty("percentage",per);
});
double percentage = (double)btn.getClientProperty("percentage");//or use it in any other object that has access to the btn object
Sadly Java doesn't support closures, so you can not modify variables outside the scope of an anonymous class. But you can access final variables, so in principle you can do something like this:
class Percentage {
double p;
}
final Percentage p = new Percentage();
btn.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
// [...]
p.p = 1/5;
// [...]
}
}
);
Then you can access the updated percentage via p.p outside of your anonymous class. (Btw. is it really a "percentage" or in fact a ratio?)
But this doesn't seem very idiomatic for Java, so the clean solution is probably just to make a proper class with a private instance variable and a getter and use this instead of the anonymous class.
I think what you actually need is just a static field (it can have whatever access modifiers you want). So something like this I think should work:
public class Test {
static double d = 0;
public static void main(String[] args) {
JButton b = new JButton("ASDF");
b.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent arg0) {
d = 5;
}
});
}
}

Trouble determining how to make my calculator calculate properly

This is probably the nth time you've received a newbie question regarding calculators, but I just can't figure it out, been working on it for two to three days. The way I have built my calculator at the moment does not suffice and I know I have to start calculating at the time I press the '=' button, but I simply can't figure out how to do so. Due to this reason I have reverted back to my original calculator code, in which it calculates when I press an operation button (like '+') which didn't work, but I was hoping that that would allow me to properly build on it. Here's the code:
package rekenmachine;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import java.util.*;
public class Rekenmachine extends JFrame
{
public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.setSize(300,500);
frame.setLocation(800,400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("Rekenmachine");
RekenPaneel rekenpaneel = new RekenPaneel();
frame.setContentPane(rekenpaneel);
frame.setVisible(true);
}
private static int getal, totaalGetal;
private boolean optellen, aftrekken, vermenigvuldigen, delen;
public int Optellen(int getal)
{
reset();
optellen = true;
totaalGetal += getal;
getal = 0;
return totaalGetal;
}
public int Aftrekken(int getal)
{
reset();
aftrekken = true;
totaalGetal -= getal;
getal = 0;
return totaalGetal;
}
public int Delen(int getal)
{
reset();
delen = true;
totaalGetal /= getal;
getal = 0;
return totaalGetal;
}
public int Vermenigvuldigen(int getal)
{
reset();
vermenigvuldigen = true;
totaalGetal *= getal;
getal = 0;
return totaalGetal;
}
public int getGetal()
{
return getal;
}
public int getTotaalGetal()
{
return totaalGetal;
}
public void reset()
{
optellen = false;
aftrekken = false;
delen = false;
vermenigvuldigen = false;
getal = 0;
totaalGetal = 0;
}
}
class RekenPaneel extends JPanel
{
JButton knop0, knop1, knop2, knop3, knop4, knop5, knop6, knop7, knop8, knop9,
knopOptel, knopAftrek, knopVermenigvuldigen, knopDelen, knopUitkomst,
knopWissen;
JTextField invoerVak;
JPanel textPaneel, knopPaneel, logoPaneel;
Rekenmachine rekenmachine;
public RekenPaneel()
{
rekenmachine = new Rekenmachine();
setLayout(new BorderLayout());
textPaneel = new JPanel();
knopPaneel = new JPanel();
logoPaneel = new JPanel();
textPaneel.setLayout(new FlowLayout());
knopPaneel.setLayout(new GridLayout(4,4));
logoPaneel.setLayout(new FlowLayout());
Border rand = BorderFactory.createEmptyBorder(10, 10, 10, 10);
knop0 = new JButton("0");
knop0.addActionListener(new knop0Handler());
knop1 = new JButton("1");
knop1.addActionListener(new knop1Handler());
knop2 = new JButton("2");
knop2.addActionListener(new knop2Handler());
knop3 = new JButton("3");
knop3.addActionListener(new knop3Handler());
knop4 = new JButton("4");
knop4.addActionListener(new knop4Handler());
knop5 = new JButton("5");
knop5.addActionListener(new knop5Handler());
knop6 = new JButton("6");
knop6.addActionListener(new knop6Handler());
knop7 = new JButton("7");
knop7.addActionListener(new knop7Handler());
knop8 = new JButton("8");
knop8.addActionListener(new knop8Handler());
knop9 = new JButton("9");
knop9.addActionListener(new knop9Handler());
knopOptel = new JButton("+");
knopOptel.addActionListener(new knopOptelHandler());
knopAftrek = new JButton("-");
knopAftrek.addActionListener(new knopAftrekHandler());
knopVermenigvuldigen = new JButton("*");
knopVermenigvuldigen.addActionListener(new knopVermenigvuldigenHandler());
knopDelen = new JButton("/");
knopDelen.addActionListener(new knopDelenHandler());
knopUitkomst = new JButton("=");
knopUitkomst.addActionListener(new knopUitkomstHandler());
knopWissen = new JButton("C");
knopWissen.addActionListener(new knopWissenHandler());
invoerVak = new JTextField(25);
invoerVak.setHorizontalAlignment(invoerVak.RIGHT);
invoerVak.setEditable(false);
invoerVak.setBackground(Color.WHITE);
textPaneel.add(invoerVak);
knopPaneel.add(knop7);
knopPaneel.add(knop8);
knopPaneel.add(knop9);
knopPaneel.add(knopDelen);
knopPaneel.add(knop4);
knopPaneel.add(knop5);
knopPaneel.add(knop6);
knopPaneel.add(knopVermenigvuldigen);
knopPaneel.add(knop1);
knopPaneel.add(knop2);
knopPaneel.add(knop3);
knopPaneel.add(knopOptel);
knopPaneel.add(knop0);
knopPaneel.add(knopWissen);
knopPaneel.add(knopUitkomst);
knopPaneel.add(knopAftrek);
add(textPaneel, BorderLayout.NORTH);
add(knopPaneel, BorderLayout.CENTER);
add(logoPaneel, BorderLayout.SOUTH);
}
class knop0Handler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
invoerVak.setText(invoerVak.getText() + "0");
}
}
class knop1Handler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
invoerVak.setText(invoerVak.getText() + "1");
}
}
class knop2Handler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
invoerVak.setText(invoerVak.getText() + "2");
}
}
class knop3Handler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
invoerVak.setText(invoerVak.getText() + "3");
}
}
class knop4Handler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
invoerVak.setText(invoerVak.getText() + "4");
}
}
class knop5Handler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
invoerVak.setText(invoerVak.getText() + "5");
}
}
class knop6Handler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
invoerVak.setText(invoerVak.getText() + "6");
}
}
class knop7Handler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
invoerVak.setText(invoerVak.getText() + "7");
}
}
class knop8Handler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
invoerVak.setText(invoerVak.getText() + "8");
}
}
class knop9Handler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
invoerVak.setText(invoerVak.getText() + "9");
}
}
class knopOptelHandler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
String invoer = invoerVak.getText();
int invoerGetal = Integer.parseInt(invoer);
rekenmachine.Optellen(invoerGetal);
invoerVak.setText("");
}
}
class knopAftrekHandler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
String invoer = invoerVak.getText();
int invoerGetal = Integer.parseInt(invoer);
rekenmachine.Aftrekken(invoerGetal);
invoerVak.setText("");
}
}
class knopVermenigvuldigenHandler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
String invoer = invoerVak.getText();
int invoerGetal = Integer.parseInt(invoer);
rekenmachine.Vermenigvuldigen(invoerGetal);
invoerVak.setText("");
}
}
class knopDelenHandler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
String invoer = invoerVak.getText();
int invoerGetal = Integer.parseInt(invoer);
rekenmachine.Delen(invoerGetal);
invoerVak.setText("");
}
}
class knopUitkomstHandler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
invoerVak.setText("" + rekenmachine.getTotaalGetal());
rekenmachine.reset();
}
}
class knopWissenHandler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
rekenmachine.reset();
invoerVak.setText("");
}
}
}
What it basically does is look like a calculator, all buttons work, yet the way it calculates is way off, if at all. I think what I need to do is save a number, when I press + it should add the next number, if I press - it should substract the next number, if I press * it should multiply by the next number and if I press / it should divide by the next number, then when I press = it should show the result, yet I have no idea how to do that.
Should it be done with an arraylist? If so, how could I properly save the result? I mean, using it with two numbers isn't that hard, you just save two numbers and do something with them, then show the result, but a person doesn't always use just two numbers.
To explain the problem I'm having more clearly: for example, when I enter '50' and then press '+' it SHOULD convert "50" to getal = 50 and start the Optellen method, then totaalGetal should become 50, it then empties the textfield. If I then add '3', it should say 53 when I press '=' yet it still shows 50 if I'm lucky. To solve that I assume I have to make the calculation WHEN I press '=' but I don't know how to save/calculate numbers before having done that.
Can anybody tell me what to do before I've lost all my hair? :P
When you click on the +, you're calling this:
knopOptel.addActionListener((ActionEvent e) ->
{
String invoer = invoerVak.getText();
int invoerGetal = Integer.parseInt(invoer);
rekenmachine.addition(invoerGetal);
invoerVak.setText("");
});
But when you click on +, you're not doing the calculation yet! What you should be doing is:
The user type a number
The user click on + (for example)
In your ActionListener, you read the number on the screen, you store it in getal, you clear the screen, and you set your boolean optel to true
The user types another number
The user click on equal
In your equal Listener, you read the number you read the number on the screen, and depending on the flag (optel in the example), you calculate the result
you display the result
So indeed, the calculation is done when you press equal.
A small code example:
knopOptel.addActionListener((ActionEvent e) ->
{
int invoerGetal = Integer.parseInt(invoerVak.getText()); // get the number
calculate(invoerGetal); //sets totalNumber to what it should be by looking at the flags
invoerVak.setText(totalNumber); // we write the temporary result
additionFlag = true; // next number must be added
});
And your calculate function should just be something like:
private void calculate(int aInvoerGetal) {
if (addition)
totalNumber += aInvoerGetal;
else if (substract)
totalNumber -= aInvoerGetal;
else if (divide)
totalNumber /= aInvoerGetal;
else if (multiply)
totalNumber *= aInvoerGetal;
resetFlags();
}
TO GO FURTHER:
Now, if you want to support multiple caculations (5+5+5+3), it's easy. When you click on +, -, *, /, you first call the equalActionListener.
This way, you get this kind of sequence:
5, + // ==> equal called ==> 5 (because the flags are all false) ==> flag + to true
10, + // ==> equal called ==> 15 because 5 in memory and + flag was on. + flag goes off, then on again (because you pressed + again)
4, = // ==> equal called ==> 19
When developing something, you have to think first how you want to solve a problem. Work from there by designing a solution. If you have a programmable solution, implement it. The UI may come later. That's a core skill that a developer should have.
1) You want to have a calculator that support +, -, / and *. The output should be shown if "=" is clicked.
2) Think with classes. That concept may be new for you, but you will discover later from. Your main class that does the calculations is Rekenmachine. (From a design perspective, it should be a stand alone class, but that's not important now). You need to separate it from your UI layer.
Your class supports the actions that you have implemented with the UI. That's good. But I also see things that shouldn't be there
public int Vermenigvuldigen(int getal)
{
reset(); // reset the calculator ?
vermenigvuldigen = true; // purpose ?
totaalGetal *= getal;
getal = 0; // resetting argument getal ?
return totaalGetal;
}
Here, I'm not sure why you're calling reset() because what it does is
public void reset()
{
optellen = false;
aftrekken = false;
delen = false;
vermenigvuldigen = false;
getal = 0;
totaalGetal = 0;
}
When reading the above method, you see that it resets the value that you tried to add on. Of course your calculation would go wrong because you're erasing previous data... resetting everything back to initial state. I also don't understand the setting to "true" or "false" on the actions. Perhaps for the UI? That is not required.
Make it simple:
When creating Rekenmachine, set the variable totaalGetal to 0 as default. That variable holds the value of your calculations performed so far. That's the start. When you have an addition, use
public void add(int getal) {
totaalGetal+= getal; // means totaalGetal = totaalGetal + getal.
}
Before calling add() you have to parse the string to an integer. This can be done in the button action:
class knop1Handler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
// get input
String input = invoerVak.getText();
// convert
int converted = convertToInt(input);
// instruct myRekenmachine to add the value
myRekenmachine.add(converted);
}
}
Important note ... use concise naming ... "knop1handler" is difficult to read. Use "addButtonHandler" to indicate that this class handles the add button.
convertToInt is a method that reads in a String and returns with an integer. You have to implement that yourself. myRekenmachine is an instance of your Rekenmachine class.
This above is for addition. Implement the same for other operands. If you want to adjust the UI, do that in the handler.
Now, when you press =, just return the totaalGetal value.
PS: Not sure, but ask if you are allowed to write names in English. My native language is Dutch, but during my CS courses, I am allowed to program completely in English. Please try to ask it because English is the main language in IT world if you're aiming for a career in IT.
Wesley, did you think about what you wanted the calculator to do before you started coding? e.g. would it support brackets, sin/cos, memory. Did you think about how logically these functions would work and then think of how they could be implemented in Java? A few flow charts and some pesudocode can go a long way when you're starting out in a new language if only to help you comprehend what it is you are trying to do.
BTW I know it's tempting to start with the GUI code and move into the logic of the application but it is usually better to start with the logic and then move onto the GUI. You can hard code the values for inputs and see if the functionaly behaves as expected and then introduce parameters with values passed in from else where.
EDIT
I think I know why your + key is not working. The reset() method is setting getal and totalGetal to 0 before adding them. 0 + 0 is 0.
knopOptel = new JButton("+");
knopOptel.addActionListener(new knopOptelHandler());
class knopOptelHandler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
String invoer = invoerVak.getText();
int invoerGetal = Integer.parseInt(invoer);
rekenmachine.Optellen(invoerGetal);
invoerVak.setText("");
}
}
public int Optellen(int getal)
{
reset();
public void reset()
{
optellen = false;
aftrekken = false;
delen = false;
vermenigvuldigen = false;
getal = 0;
totaalGetal = 0;
}
optellen = true;
totaalGetal += getal;
getal = 0;
return totaalGetal;
}

Restrict Input of JTextField to Double Numbers?

In java , i am trying to make simple currency converter, but for that i need a text field which can restrict input to numbers only and more importantly double numbers. I tried using JFormatedTextField but it only format the input after you have done your input and click elsewhere but i need to restrict TextField to consume() each invalid character while doing input.
Possible Attempts:
Using JFormatedTextField:
JFormatedTextField textField = new JFormatedTextField(new DoubleFormat());
textField.setBounds(190, 49, 146, 33);
frame.getContentPane().add(textField);
textField.setColumns(10);
Using KeyTyped Event:
char c = arg0.getKeyChar();
if(!(Character.isDigit(c) || c == KeyEvent.VK_BACK_SPACE || c== KeyEvent.VK_DELETE)){
arg0.consume();
}
Using KeyTyped Event with regex:
if(!((textField.getText().toString+arg0.getKeyChar()).matches("[0-9]*(.[0-9]*)?"))){
arg0.consume();
}
Second and third attempt were close but then second attempt failed on point values and third attempt always read first character on textField no matter what it is, So any suggestions ? i am not very fond of JAVA GUI so kindly be patient.
If you know how many places before and after decimal point you want, you can also use MaskFormatter. For example:
JFormattedTextField field = new JFormattedTextField(getMaskFormatter("######.##"));
(...)
private MaskFormatter getMaskFormatter(String format) {
MaskFormatter mask = null;
try {
mask = new MaskFormatter(format);
mask.setPlaceholderCharacter('0');
}catch (ParseException ex) {
ex.printStackTrace();
}
return mask;
}
However it will chenge a look of JTextField, so it will be always visible 000000.00 in it.
EDIT
Another way, not too elegant, but in my opinion working. Try with DecumentListener, maybe it will suit your needs:
field = new JFormattedTextField();
field.getDocument().addDocumentListener(new DocumentListener() {
#Override
public void insertUpdate(DocumentEvent e) {
Runnable format = new Runnable() {
#Override
public void run() {
String text = field.getText();
if(!text.matches("\\d*(\\.\\d{0,2})?")){
field.setText(text.substring(0,text.length()-1));
}
}
};
SwingUtilities.invokeLater(format);
}
#Override
public void removeUpdate(DocumentEvent e) {
}
#Override
public void changedUpdate(DocumentEvent e) {
}
});
I used regex: \\d*(\\.\\d{0,2})? because two decimal places is enough for currency.
You would need to use a DocumentFilter. Read the section from the Swing tutorial on Implementing a DocumentFilter for an example to get you started.
Your implementation will be more complex because you will need to take the text already in the Document and then insert the new text in the appropriate location in the String and then invoke Double.parseDouble(...) on the String to make sure it is a valid double value.
If the validation succeeds then you continue with the insertion otherwise you can generate beep.
You can add a key listener to the text field and implement the keyReleased() method to determine if they value in the text field is a double after every key stroke by the user.
public class CurrencyJTF extends JFrame {
JButton jButton = new JButton("Unfocus");
final JFormattedTextField textField = new JFormattedTextField(new DecimalFormat());
double lastDouble = 0.0;
public CurrencyJTF() throws HeadlessException {
textField.setColumns(20);
textField.setText(lastDouble + "");
this.setLayout(new FlowLayout());
this.add(textField);
this.add(jButton);
textField.addKeyListener(new KeyAdapter() {
#Override
public void keyReleased(KeyEvent e) {
handleKeyReleased();
}
});
}
private void handleKeyReleased() {
String text = textField.getText();
if (text.isEmpty()) return;
try {
lastDouble = Double.parseDouble(text);
} catch (NumberFormatException ex) {
textField.setText(lastDouble + ""); // or set to other values you want
}
}
public static void main(String[] args) {
JFrame frame = new CurrencyJTF();
frame.setVisible(true);
frame.pack();
}
}
You can write your own KeyListener something like that:
public class DoubleNumbersKeyListener implements KeyListener {
final HashSet<Character> valid_keys = new HashSet<>();
final ArrayList<Character> sequence = new ArrayList<>();
public DoubleNumbersKeyListener() {
valid_keys.add('.');
valid_keys.add('0');
valid_keys.add('1');
valid_keys.add('2');
valid_keys.add('3');
valid_keys.add('4');
valid_keys.add('5');
valid_keys.add('6');
valid_keys.add('7');
valid_keys.add('8');
valid_keys.add('9');
valid_keys.add((char) KeyEvent.VK_BACK_SPACE);
valid_keys.add((char) KeyEvent.VK_DELETE);
}
#Override
public void keyTyped(KeyEvent event) {
char c = event.getKeyChar();
if (!valid_keys.contains(c)) {
event.consume();
} else {
if (c == KeyEvent.VK_DELETE || c == KeyEvent.VK_BACK_SPACE) {
if (!sequence.isEmpty()) {
char last = sequence.remove(sequence.size() - 1);
if (last == '.') {
valid_keys.add(last);
}
}
} else {
sequence.add(c);
if (c == '.') {
valid_keys.remove(c);
}
}
}
}
#Override
public void keyPressed(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
}
}

How to change a Jbutton's function on clicking another Jbutton?

I am writing a program which will convert weight in pounds to kilograms and also weight in Kilograms to pounds. The output window is as follows:
When I want to convert Kilograms to Pounds I click switch button and the output changes as follows:
But the problem is when I click "Convert" it still converts weight to Kilogram instead of Pounds.
I want the "Convert" button's function to change when I click the "Switch" button so it will convert the weight in Kilograms to pounds. Please help.
My source code is as follows:
public class convertApp extends JFrame implements ActionListener {
private JLabel poundlbl = new JLabel("Weight in Pounds");
private JLabel kglbl = new JLabel("Weight in Kilograms");
private JTextField poundbx= new JTextField(12);
private JTextField kgbx= new JTextField(12);
private JButton conbtn=new JButton("Convert");
private JButton switchbtn=new JButton("Switch");
private JButton newconbtn=new JButton("Convert");
private JPanel bxPanel = new JPanel();
public convertApp(){
super("Weight Converter");
bxPanel.setLayout(new GridLayout(5,29,5,5));
bxPanel.add(poundlbl);
bxPanel.add(poundbx);
bxPanel.add(kglbl);
bxPanel.add(kgbx);
bxPanel.add(conbtn);
bxPanel.add(switchbtn);
//bxPanel.setBackground(Color.gray);
this.setLayout(new GridLayout(1,1,0,0));
this.add(bxPanel);
this.setVisible(true);
//what to do if i close
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//put window in the center
this.setLocationRelativeTo(null);
//disable resize
this.setResizable(false);
//pack all the components within the window
this.pack();
conbtn.addActionListener(this);
switchbtn.addActionListener(this);
}
public void actionPerformed(ActionEvent evnt){
if(evnt.getSource()==conbtn){
String poundtext = poundbx.getText();
int pound = Integer.parseInt(poundtext);
double kilo = pound * 0.453592;
kgbx.setText(""+kilo);
}
else if(evnt.getSource()==switchbtn)
{
poundlbl.setText("Weight in Kilograms:");
kglbl.setText("Weight in Pounds:");
if(evnt.getSource()==conbtn){
String kilotext = poundbx.getText();
int kilo = Integer.parseInt(kilotext);
double pound = kilo * 2.20462;
kgbx.setText(""+pound);
}
}
}
}
Create boolean Variable
boolean switch=true;
void kiloGramToPound{
//Convert Codes Here
}
void PoundToKiloGram{
//Convert Codes Here
}
Convert Button actionPerformed
if(switch==true){
kiloGramToPound();
}else{
PoundToKiloGram();
}
Switch Button actionPerformed
if(switch==true){
switch=false;
}else{
switch=true;
}
You cannot change the function itself. You can create a flag that sets true or false (your choice) when you click the 'switch' button. Then check the value of that flag when you click 'convert' and perform the appropriate conversion according to your flag convention.
i.e.
Boolean isPtoK = true;
// [...]
if(isPtoK){
// convert pounds to kilos
} else{
// kilos to pounds
}
I would create a separate function that switches the value of your flag when 'switch' is clicked.
Apologies for not answering your question, but may I suggest you to try KeyListener/KeyAdapter instead of the combination of ActionListeners and buttons.
Example:
textField1.addKeyListener(new ConverterListener(textField2, "2.20462"));
textField2.addKeyListener(new ConverterListener(textField1, "0.453592"));
class ConverterListener extends KeyAdapter {
JTextField destination;
String multiplier;
public ConverterListener(JTextField destination, String multiplier) {
this.destination = destination;
this.multiplier = multiplier;
}
#Override
public void keyReleased(KeyEvent e) {
JTextField source = (JTextField) e.getSource();
String result = convert(source.getText(), multiplier);
destination.setText(result);
}
private String convert(String value, String multiplier) {
String result = "0";
try {
double dblValue = value.isEmpty() ? 0d : Double.parseDouble(value);
double dblMultiplier = value.isEmpty() ? 0d : Double.parseDouble(multiplier);
result = Double.toString(dblValue * dblMultiplier);
} catch (Exception e) {
System.out.println(e);
}
return result;
}
}

Categories