For practice, I am trying to create a fully functional calculator. I copied the ActionListener class of my code below. I feel like my this method for getting the users input, storing it as an integer/double does not work well as it is too basic and does not work in all cases. I was wondering if anyone can help me figure out a way to structure my code, get user input for two numbers and a symbol, and basically create a fully function GUI calculator. My problem is getting user input from my JButton, storing as a number that in way like a calculator does, (press 1 twice == 11) and using it for later calculation.
I appreciate any advice in this regard.
private class TheHandler implements ActionListener{
public void actionPerformed(ActionEvent event){
while(equals!=event.getSource())
if(one==event.getSource()){
result.setText("1");
num1=1;
}
else if(two==event.getSource()){
result.setText("2");
}
else if(three==event.getSource()){
result.setText("3");
}
else if(four==event.getSource()){
result.setText("4");
}
else if(five==event.getSource()){
result.setText("5");
}
else if(six==event.getSource()){
result.setText("6");
}
else if(seven==event.getSource()){
result.setText("7");
}
else if(eight==event.getSource()){
result.setText("8");
}
else if(nine==event.getSource()){
result.setText("9");
}
else if(zero==event.getSource()){
result.setText("0");
}
}
}
You should remove the while at all.
I would suggest to use numeric vars like
long num = 0;
int digit;
Each event should just set digit
...
else if(nine==event.getSource()){
digit = 9;
} else if(zero==event.getSource()){
digit = 0;
}
...
num = num * 10 + digit;
...
result.setText(Long.toString(num));
How about a class member variable to store the current state of the display and use that for set text?
private class TheHandler implements ActionListener{
String display = "";
public void actionPerformed(ActionEvent event){
while(equals!=event.getSource()){
if(one==event.getSource()){
display=display+"1";
}
.....
}
result.setText(display);
}
}
You could more cleanly associate each button with a number like so:
private class TheHandler implements ActionListener{
private Map<Object, String> numbers = new HashMap<Object, String>();
{
numbers.put(zero, "0");
numbers.put(one, "1");
...
}
public void actionPerformed(ActionEvent event){
Object source = event.getSource();
while(equals != source){
String number = numbers.get(source);
if (number != null){
result.setText(number);
}
}
}
}
Related
i am trying to reach the value within an int variable from within the actionPerformed class, the integer comes from another class where its passed as an argument "asd" and holds the value "1". I obviously deleted some lines from the code i posted below to make it easier to read but what i ve deleted has nothing to do with the problem im having.
So here, the output i see is;
asd
1
1
0
0
the last two outputs are from the actionPerformed class, they appear when i click the related button. How can i make it so those 2 outputs are also shown as 1?
public class customerAppointmentScreen extends JFrame implements ActionListener{
private JButton massB,indiB;
public int asd,id;
public customerAppointmentScreen(int asd) {
System.out.println("asd ");
System.out.println(asd);
id=asd;
System.out.println(id);
}
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if(e.getSource()==massB) {
int id=asd;
System.out.println(asd);
System.out.println(id);
//this.setVisible(false);
}
else if(e.getSource()==indiB) {
this.setVisible(false);
}
}
}
Starting with...
public int asd,id;
public customerAppointmentScreen(int asd) {
System.out.println("asd ");
System.out.println(asd);
id=asd;
System.out.println(id);
}
The parameter asd is never assigned to the instance field asd, so the instance field remains 0 (id on the other hand is equal to the parameter asd)
When the ActionListener is triggered...
public void actionPerformed(ActionEvent e) {
if (e.getSource() == massB) {
int id = asd;
System.out.println(asd);
System.out.println(id);
//this.setVisible(false);
} else if (e.getSource() == indiB) {
this.setVisible(false);
}
}
You assign the instance field asd value to the local variable id, since asd is still zero, so is id.
The "simple" solution would be to assign the parameter from the constructor to the appropriate instance field OR use the correct instance field in the ActionListener, depending on your intentions.
I have one JFrame called User where I declare a variable called id and set it to a certain value depending on some conditions.
I need to use this variable in a second JFrame called output.
This is the code I have
class InputScreen extends javax.swing.JFrame {
public int id = 0;
private void submitButtonActionPerformed(java.awt.event.ActionEvent evt) {
if (condition){
id = 1;
System.out.println(id);
}
elseif (condition){
id = 2;
System.out.println(id);
}
elseif (condition){
id = 3;
System.out.println(id);
}
else{
System.exit(0);
}
I used a constructor in the frame Output but it doesn't seem to work.
public class Output extends javax.swing.JFrame {
int rule;
public Output(int Id){
rule = Id;
initComponents();
}
public Output() {
initComponents();
conn = MySqlConnect.ConnectDB();
}
Updated Code
Frame - Input
class InputScreen extends javax.swing.JFrame {
public int id = 0;
public int getID(){
return input_rule_id;
}
private void submitButtonActionPerformed(java.awt.event.ActionEvent evt) {
if (condition){
id = 1;
System.out.println(id);
}
elseif (condition){
id = 2;
System.out.println(id);
}
elseif (condition){
id = 3;
System.out.println(id);
}
Form - Output
private void formWindowActivated(java.awt.event.WindowEvent evt) {
Input InSc = new Input();
InSc.getId();
}
All primitive data-types will be passed by the value. Use an object wrapper to pass the value by the reference. For example AtomicInteger
class InputScreen extends javax.swing.JFrame {
private AtomicInteger id = new AtomicInteger(0);
private void submitButtonActionPerformed(java.awt.event.ActionEvent evt) {
if (condition){
id.set(1);
System.out.println(id);
}
else if (condition){
id.set(2);
System.out.println(id);
}
else if (condition){
id.set(3);
System.out.println(id);
}
else{
System.exit(0);
}
}
public class Output extends javax.swing.JFrame {
AtomicInteger rule;
public Output(AtomicInteger Id){
rule = Id;
initComponents();
}
public Output() {
initComponents();
conn = MySqlConnect.ConnectDB();
}
}
Parameter passing
The most simple way would be passing Output as a parameter to InputScreen. Then you might just call a method Output.setId(id) within your InputScreen.submitButtonActionPerformed() logic. This way however is a bit problematic, when the application grows.
Observer Pattern
A better way would be realizing a IdChangedListener as part of an Observer pattern as a proxy to the ActionListener you already have implemented. When your ActionListener fires, you call all IdChangeListeners that have registered as Observers to InputScreen. In Output you provide a method setId(id) to provide access. In the place you instantiate the two JFrames you implement an IdChangeListener, add it to InputScreen and when it fires you call Output.setId().
Anyway, you see a lot of work (and code) for just one event. Also this approach has its limitations concerning application size and dynamic.
In Memory EventBus
The up-to-date approach would be using a in memory EventBus. This eliminates the hard-wiring of the components within your UI and reduces the code size. However, it limits the reuse of components because they will be automatically react to some events. What if you have them more than once? Listening to different Events?
You need to think about where you want to use which approach. I would suggest using an EventBus for event propagation between the concrete components of your application. Use Observer pattern on medium size components while use parameter passing for small size or very static ones.
You can use getters and setter. Define a getter method in your Frame from where you want to pass the id variable. eg
public int getID(){
return id;
}
In your other frame you can just use this method to return the result. int id = getID();
Another work around for this problem is making the variable globe and static so it can be imported in the other frame and be used.
I have been stuck for days trying to figure out why I cannot get the value from the inurancevaluetextfield. I have attached both files so that if anyone wants to run it they can see my problem. I get to the stage where I select Insurance checkbox and enter a value between 100 and 2000, but I keep getting the error message stating my value is not between those amounts. So I don't think the textfield is being read at all.
public void setInsurancecost(double insurancecost)
{
this.insurancecost = insurancecost;
}
public double getInsurancecost()
{
if (value < 100)
{ JOptionPane.showMessageDialog(null, "Insurance can only be purchased for items valued between $100 - $2000.");
}
else if (value >= 100)
{ insurancecost = value * 0.05;
}
else if (value > 2000)
{ JOptionPane.showMessageDialog(null, "Insurance can only be purchased for items valued between $100 - $2000.");
}
return insurancecost;
}
public class TextFieldHandler implements ActionListener
{
#Override
public void actionPerformed (ActionEvent e)
{
DecimalFormat df = new DecimalFormat("0.00");
String valueStr=insurancevaluetextField.getText();
value=Double.parseDouble(valueStr);
}
}
private class DoListener implements ActionListener
{
#Override
public void actionPerformed(ActionEvent e)
{
DecimalFormat df = new DecimalFormat("0.00");
String arg = e.getActionCommand();
if (arg.equals("Calculate Insurance"))
{
System.out.println( "calculate insurance button selected");
add (insuranceDisplayArea);
insuranceDisplayArea.setText("The insurance charge for your package is: $"+df.format(getInsurancecost())+"\n");
}
You are assigning the variable value at TextFieldHandler. The action performed event of a JTextField will fire at the Enter key event. It will be solved if you assign the variable at the beginning of DoListener.actionPerformed(). So that only thing you need is to move the code in TextFieldHandler.actionPerformed() to DoListener.actionPerformed()
I looked at your code. TheTextFiled handler you have registered with textField only invoked when you press enter key on text field.
TextFieldHandler handler = new TextFieldHandler();
textField.addActionListener(handler);
Therefore actionPerformed in TextFieldHandler only invoked if you press enter on textField and that moment only your insurancevaluetextField read and set to value.
You can either change the listener so that text filed key change will capture value or just add textfiled read logic into calculate button listener. i.e DoListener
private class DoListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
DecimalFormat df = new DecimalFormat("0.00");
String weightStr = textField.getText();
weight = Double.parseDouble(weightStr);
String valueStr = insurancevaluetextField.getText();
value = Double.parseDouble(valueStr);
.... }
I would suggest the changing DoListener.
when you are using API read about it. Know what they do exactly.
Also debug the program using good IDE. You will spot the error very quickly.
ActionListener event will occur on TextField only when you type something and hit enter.
this handler will not be raised, insurancevaluetextField.addActionListener (handler);
its value will be 0, that why the error message was displayed if you dont hit enter after typing
we are working on a project trying to make a message in a JOptionPane show up when a button is pressed and certain conditions are met. However whenever the code is activated and a button is pressed, the JOptionPane shows up with no message. Here is the code that creates the GUI
package BlackJack;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class BlckJckUI {
public static void main(String[] args) {
JFrame GUI = new JFrame("Blackjack Advisor");
GUI.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
GUI.setSize(1000,900);
GUI.setVisible(true);
JButton two = new JButton(Two);
two.setSize(300, 100);
two.setLocation(100, 200);
two.addActionListener(new ActionListener ()
{
public void actionPerformed(ActionEvent e)
{
Arrays array = new Arrays();
Math math = new Math();
math.cardvalue = 2;
array.clicktracker++;
JOptionPane.showMessageDialog(null,array.result);
}
});
GUI.add(two);
This is the code that works out the logic.
package BlackJack;
public class Math {
public int cardvalue;
public Math()
{
Arrays array = new Arrays();
if (array.clicktracker == 1)
{
array.dealer = cardvalue;
array.result = "Please select the first card you have :)";
}
else if (array.clicktracker == 2)
{
array.playerhand.add(cardvalue);
array.result = "Please select the second card you have :)";
}
else if (array.clicktracker >= 3)
{
array.playerhand.add(cardvalue);
if (array.playerhandtotal <= 8)
{
// array.result = result statement
array.result = "You should just hit until you're safe. If the dealer 6 or below,\n"
+ " the chances are that he'll bust and if not, remain low above 17.\n"
+ " As long as you can pull a 17 or higher, you should be safe. Pick \n"
+ "another card or reset.";
This is the code that creates the Array and variables associated with it.
package BlackJack;
import java.util.ArrayList;
public class Arrays{
public String result = null;
ArrayList<Integer> playerhand = new ArrayList<Integer>();
public int dealer = 0;
public int clicktracker = 0;
public int playerhandtotal = 0;
{
for (int element: playerhand)
{
playerhandtotal = element + playerhandtotal;
}
System.out.println(result);
System.out.println(dealer);
System.out.println(clicktracker);
}
}
In your Math constructor, you are changing the result of a different type of array.result than the one you are trying to display.
I would consider passing the Arrays instance into the Math constructor so that you can modify the result from there. Be sure to not reassign the instance though.
public void actionPerformed(ActionEvent e)
{
Arrays array = new Arrays();
Math math = new Math(array);
math.cardvalue = 2;
array.clicktracker++;
JOptionPane.showMessageDialog(null,array.result);
}
...
public Math(Arrays array)
{
if (array.clicktracker == 1)
{
// And so on ...
The problem is that you are creating two separate instances of your Arrays class. Once in the actionPerformed method and also within the constructor of your Math class.
This code you currently have:
Arrays array = new Arrays();
Math math = new Math();
math.cardvalue = 2;
array.clicktracker++;
JOptionPane.showMessageDialog(null,array.result);
will display the result of the Arrays object you created in the actionPerformed method - which is null as the result of this object is initialised to null and never set.
This has been mentioned in other answers and comments and will solve it from producing null but this approach will now always yield the same result as you are still always creating a new instance of your Arrays class in your actionPerformed method.
A better approach would be to separate the logic of the result from the constructor of your Math class into another method and create this instance of your Math class outside of the actionPerformed method. Then within your actionPerformed method call your method which will do the logic for your result.
In UI:
Math math = new Math();
two.addActionListener(new ActionListener ()
{
public void actionPerformed(ActionEvent e)
{
math.cardvalue = 2;
math.array.clicktracker++;
math.calcResult();
JOptionPane.showMessageDialog(null,math.array.result);
}
});
In Math:
public class Math {
public int cardvalue;
public Arrays array;
public Math()
{
array = new Arrays();
}
public void calcResult(){
if (array.clicktracker == 1)
{
//...rest of your logic
}
}
I'm doing the Guessing Game for Java homework and I am having a logic problem with the nested if else. I am trying to determine two things: is the number to high/low, and if the user is getting hotter/colder. I have a variables intGuess and intOldGuess. I am trying to compare the two for the hotter/colder but I either end up with intOldGuess being 0, or the same as intGuess when it comes time for comparison. Neither are correct of course. Here is what I have so far:
Here is the section I think is giving me trouble:
public void actionPerformed(ActionEvent e)
{
int intGuess = 0, intOldGuess;
intOldGuess = intGuess;
try
{
intGuess = Integer.parseInt(txaUserGuess.getText().trim());
if (intGuess < intRandomNum)
{
lblHighLow.setText("Too Low");
if (intGuess > intOldGuess)
{
lblHotCold.setText("Getting Colder");
System.out.println(intOldGuess);
System.out.println(intGuess);
}
Here is the entire code if you need it:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
public class GuessNumber extends JFrame
{
private JTextField txaUserGuess;
private JLabel lblStart, lblPrompt, lblHighLow, lblHotCold;
private JButton btnGuess, btnQuit, btnAgain;
private int intRandomNum;
Container c = getContentPane();
public static void main(String args[])
{
GuessNumber app = new GuessNumber();
}
public GuessNumber()
{
super("Guessing Game");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Creates components
btnGuess = new JButton("Guess");
btnQuit = new JButton("Quit");
btnAgain = new JButton("Play Again?");
lblStart = new JLabel("I have a number between 1 and 1000.");
lblPrompt = new JLabel(
"Can you guess my number? Please enter your guess:");
lblHighLow = new JLabel("");
lblHotCold = new JLabel("");
txaUserGuess = new JTextField(5);
setLayout(new FlowLayout());
c.add(lblStart);
c.add(lblPrompt);
c.add(txaUserGuess);
c.add(btnGuess);
c.add(btnQuit);
c.add(btnAgain);
c.add(lblHighLow);
c.add(lblHotCold);
setSize(350, 200);
setVisible(true);
btnAgain.setVisible(false);
RandomNumber();
FirstGuessButtonHandler ghandler = new FirstGuessButtonHandler();
btnGuess.addActionListener(ghandler);
QuitButtonHandler qhandler = new QuitButtonHandler();
btnQuit.addActionListener(qhandler);
AgainButtonHandler ahandler = new AgainButtonHandler();
btnAgain.addActionListener(ahandler);
}
private void RandomNumber()
{
intRandomNum = new Random().nextInt(1000) + 1;
System.out.println(intRandomNum);
}
class QuitButtonHandler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
System.exit(0);
}
}
class AgainButtonHandler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
}
}
class FirstGuessButtonHandler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
int intGuess = 0, intOldGuess;
intOldGuess = intGuess;
try
{
intGuess = Integer.parseInt(txaUserGuess.getText().trim());
if (intGuess < intRandomNum)
{
lblHighLow.setText("Too Low");
if (intGuess > intOldGuess)
{
lblHotCold.setText("Getting Colder");
System.out.println(intOldGuess);
System.out.println(intGuess);
} else if (intGuess < intOldGuess)
{
lblHotCold.setText("Getting Hotter");
}
} else if (intGuess > intRandomNum)
{
lblHighLow.setText("Too High");
} else
{
c.setBackground(Color.GREEN);
lblHighLow.setText("\n\tCorrect!");
txaUserGuess.setEditable(false);
btnAgain.setVisible(true);
btnGuess.setEnabled(false);
}
} catch (NumberFormatException e1)
{
lblHighLow.setText("\n\tEnter a VALID number!");
}
}
}
}
int intGuess = 0, intOldGuess;
is currently contained in the method actionPerformed() these need to be declared as fields (outside methods but in the class body).
Also you may consider writing those as
int intGuess = 0;
int intOldGuess;
for clarity sake (it looks cleaner and will make your code more easily readable)
intOldGuess is local variable to the method. So every time the method gets called, it gets initialized to 0 (default value).
To preserve the value, you might want to create the variable as class field
class FirstGuessButtonHandler implements ActionListener
{
int intOldGuess;
public void actionPerformed(ActionEvent e)
{
int intGuess = 0;
But remember, in above case, you need to maintain the same instance of FirstGuessButtonHandler class, since the class fields are maintained per instance of the class.
Other approach could be to create intOldGuess as static class field too
In this place here:
int intGuess = 0, intOldGuess;
intOldGuess = intGuess;
You are defining intOldGuess, but in second line you assign value 0 to it. You probably should keep this variable in class scope and don't assign 0 to it.
Use of local variables should be avoided, if you want to use them without re-initialization.
To retain the value of variables make those variables Reference variable.
You can do this-
class ClassName{
int oldguess;
public void yourMethod(){
int newGuess = 0;
if (intGuess < intRandomNum)
{
lblHighLow.setText("Too Low");
if (intGuess > intOldGuess)
{
lblHotCold.setText("Getting Colder");
System.out.println(intOldGuess);
System.out.println(intGuess);
}
The problem is, that you have the second if nested in the first. The second only ever gets checked, if the first is valid. The second condition can therefore never be true. (It only checks if intGuess is greater than inOldGuess, if intGuess is less than intOldGuess, which can never be.
You need to take the second if out of the first.
Also, you seem to want to store data in intOldGuess, but you declared it as a local variable. You need to set it is a field if you want it to store data between method calls.
The problem lies with how you are keeping state
int intGuess = 0, intOldGuess;
intOldGuess = intGuess;
Here you are declaring local variables, which are recreated each time your function is called.