Calculator issue with simple logic - java

I'm new to Java and have set myself the task of trying to create a simple calculator (and GUI) to advance my understanding and skills of the language.
Take this code:
import java.awt.FlowLayout;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class calc extends JFrame {
public JTextField input;
public JTextField output;
public JPanel Window;
public JButton math_button[] = new JButton[5];
public JButton number_button[] = new JButton[10];
public String[] number_button_name = {"1","2","3","4","5","6","7","8","9","0"};
public String[] name = {"Add", "Mulitply", "Divide", "Subtract", "Equals"};
public JFrame frame = new JFrame();
public JPanel math_panel = new JPanel();
public JPanel number_panel = new JPanel();
public JTextField math_input = new JTextField();
boolean trrgger = false;
thehandler handler = new thehandler();
public void go()
{
for(int b=0; b<number_button.length; b++)
{
number_button[b] = new JButton(number_button_name[b]);
number_button[b].addActionListener(handler);
number_panel.add(number_button[b]);
}
for(int i=0; i<math_button.length;i++)
{
math_button[i] = new JButton(name[i]);
math_button[i].addActionListener(handler);
math_panel.add(math_button[i]);
}
frame.getContentPane().add(BorderLayout.NORTH, math_input);
frame.getContentPane().add(BorderLayout.SOUTH, math_panel);
frame.getContentPane().add(BorderLayout.CENTER, number_panel);
frame.setSize(400,400);
frame.setVisible(true);
}
//Method to handle the math and return the results of whichever 'button' was pressed
static int Math(String button_num, int first_num, int second_num)
{
int total = 0;
if(button_num == "Add")
{
total = first_num + second_num;
}
else if (button_num == "Mulitply") //multiply
{
total = first_num * second_num;
}
else if (button_num == "Divide") //divide
{
total = first_num / second_num;
}
else if (button_num == "Substract") //subtract
{
total = first_num - second_num;
}
else if (button_num == "Equals") //subtract
{
total = total;
}
return total;
}
//Action Events - Code that is triggered once the associated button is clicked
public class thehandler implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
for (int h = 0; h <math_button.length; h++)
{
if(event.getSource()==math_button[h])
{
int firstn = Integer.parseInt(math_input.getText());
math_input.setText("");
int secondn = Integer.parseInt(math_input.getText());
System.out.println(calc.Math(math_button[h].getText(), firstn, secondn));
}
}
for(int n=0; n<number_button.length; n++)
{
if(event.getSource()==number_button[n])
{
String number_clicked = (number_button[n].getText());
String number = math_input.getText();
math_input.setText(number + number_clicked);
}
}
}
}
}
The idea behind this code is to create a simple GUI and allows the user to input the desired amount of numbers and then press the 'equals' button to display the result. However, as stated I'm having a problem with the logic. I can get the first entered number from the JTextField, clear the text once the first variable has been initialized but this is where the program falls over. The variable 'second_num' is passed to the 'Math' method as blank (which throws up errors) because that's what I tell the ActionEvent to do in order to allow for more fluid use of the program, no user wants to have to keep clearing the input box when using a calculator.
Anybody got any ideas?
Thanks

int firstn = Integer.parseInt(math_input.getText());
math_input.setText("");
int secondn = Integer.parseInt(math_input.getText());
What exactly do you expect the above lines to do? You are getting the text from math_input. Then you set it to an empty string. And by immediately getting the string back you are expecting to get something other than empty string?
The correct approach would be:
First time the handler is called (i.e. a "math" button is clicked) collect the input. Store it somewhere.
Next time this handler will be called you will have your next input. And so on until the user clicks on "=" to evaluate the whole expression.
Advice: If you are new to java, you might find it easier to create a calculator on the command line first. The functionality of a calculator does not require a GUI. In command line collecting the input is more simple. If you get that working then you can proceed to more fancy stuff like Swing

I looked at your code but its sound complicated for me. I recommend you to use IDE like Netbeans. Create swing application. To add two number all you need to do is as follow
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
int input_1 = Integer.parseInt(jTextField1.getText());
int input_2 = Integer.parseInt(jTextField2.getText());
jTextField3.setText(String.valueOf((input_1+input_2)));
}
http://i.stack.imgur.com/1G4v7.jpg

Related

Buggy JCombobox - KeyPressed

With a JComboBox containing some elements beginning with repeated letters, typing in the character twice will return the character typed, followed by the first character of its type. For example, typing "bb" in a list containing ba, bb, and bc will return ba. However, if this list also contains bbd, continuing to press a "d" will return the bbd option. This is the same with numbers: Typing "33" returns 30, while typing "334" returns 334.
Is there a way to fix this so that a double keyPress really returns what is typed in?
Quick sample program:
String[] range = new String[401];
for (int i = 0; i <= 400; i++) {
range[i] = "" + i;
}
private javax.swing.JComboBox<String> jComboBox1;
jComboBox1 = new javax.swing.JComboBox<>();
getContentPane().setLayout(new java.awt.GridLayout());
jComboBox1.setModel(new javax.swing.DefaultComboBoxModel<>(range));
getContentPane().add(jComboBox1);
pack();
Item selection via keyboard is controlled by the JComboBox.KeySelectionManager, which, surprisingly, you can actually implement and change 😱
The one thing that the default implementation does is, it will try and find items which match the key stroke based on the first character of the item (when converted to a String via toString). The "neat" thing about this is, it will search from the currently selected item (if not null), if it can't find another matching item, it will start at the beginning of the model instead.
What this means is, if you type 3 repeatedly, it will, progressively move through all the items that start with 3. (30, 31, 32 ... 39, 300 ...)
Buuuut, this isn't what you apparently want, so, instead, you're going to have to supply your own algorithm.
One, very important consideration is, what happens when the user stops typing? If the user has typed 33, stops, then types 3 again, what should happen? Should it select 3 or 333?
The following is a VERY basic example, based on the DefaultKeySelectionManager used by JComoBox by default. It uses a StringBuilder to keep track of the key strokes and a Swing Timer which provides a 250 millisecond timeout, which will clear the StringBuilder after 250 milliseconds of inactivity (you could pass this value into the constructor to define your own)
When called by the JComboBox, it will simply do a linear search of the model for a item whose toString result starts with what's been typed.
This example is a case insensitivity, but you can modify it to meet your particular needs
public class MyKeySelectionManager implements KeySelectionManager {
private Timer timeout;
private StringBuilder pattern = new StringBuilder(32);
public MyKeySelectionManager() {
timeout = new Timer(250, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
pattern.delete(0, pattern.length());
}
});
timeout.setRepeats(false);
}
#Override
public int selectionForKey(char aKey, ComboBoxModel<?> model) {
timeout.stop();
pattern.append(Character.toLowerCase(aKey));
String match = pattern.toString();
for (int index = 0; index < model.getSize(); index++) {
String text = model.getElementAt(index).toString().toLowerCase();
if (text.startsWith(match)) {
timeout.start();
return index;
}
}
timeout.start();
return -1;
}
}
Runnable example
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ComboBoxModel;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JComboBox.KeySelectionManager;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.border.EmptyBorder;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
DefaultComboBoxModel<String> model = new DefaultComboBoxModel<>();
for (int index = 0; index < 50; index++) {
model.addElement(Integer.toString(index));
}
JComboBox cb = new JComboBox(model);
cb.setKeySelectionManager(new MyKeySelectionManager());
JFrame frame = new JFrame();
JPanel content = new JPanel(new GridBagLayout());
content.setBorder(new EmptyBorder(32, 32, 32, 32));
content.add(cb);
frame.setContentPane(content);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class MyKeySelectionManager implements KeySelectionManager {
private Timer timeout;
private StringBuilder pattern = new StringBuilder(32);
public MyKeySelectionManager() {
timeout = new Timer(250, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
pattern.delete(0, pattern.length());
}
});
timeout.setRepeats(false);
}
protected int indexOf(Object item, ComboBoxModel<?> model) {
for (int index = 0; index < model.getSize(); index++) {
if (model.getElementAt(index) == item) {
return index;
}
}
return -1;
}
#Override
public int selectionForKey(char aKey, ComboBoxModel<?> model) {
timeout.stop();
pattern.append(Character.toLowerCase(aKey));
String match = pattern.toString();
for (int index = 0; index < model.getSize(); index++) {
String text = model.getElementAt(index).toString().toLowerCase();
if (text.startsWith(match)) {
timeout.start();
return index;
}
}
timeout.start();
return -1;
}
}
}
Don't forget to take a look at JComboBox#setKeySelectionManager for more details

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;
}

Minesweeper Object GUI

I am trying to do a simple Minesweeper game using JFrame, however I am having troubles with the creation of objects. I am creating 96 buttons, some of which get the property of being wrong ("F") and right ("R"):
public class GUIBase extends JFrame {
private JButton button;
private JButton fButton;
public GUIBase() {
super("Minesweeper");
setLayout(new FlowLayout());
//Fields
int position;
for (int i = 0; i < 96; i++) {
position = (int) (Math.random() * 100);
if (position < 80) {
button = new JButton("R");
button.setToolTipText("Is this the correct one?");
add(button);
} else {
fButton = new JButton("F");
fButton.setToolTipText("Is this the correct one?");
add(fButton);
}
}
I then use ActionListener in order to check whether or not the button is correct. If the button is correct, it will get .setEnabled(false), otherwise the game ends:
//Action
Action action = new Action();
button.addActionListener(action);
fButton.addActionListener(action);
}
private class Action implements ActionListener {
public void actionPerformed(ActionEvent event) {
System.out.println("Somethin");
if (event.getSource() == button) {
button.setEnabled(false);
} else if (event.getSource() == fButton) {
JOptionPane.showMessageDialog(null, "You lost!");
System.exit(0);
} else {
JOptionPane.showMessageDialog(null, "An error ocurred");
System.exit(0);
}
}
}
Everything in the game turns out as planned, however only the last correct button ("R") and last wrong one ("F") are connected to the ActionListener. The rest of the buttons do not do anything when pressed.
How can I fix this?
The problem is that you only have two variables (attributes of the class GUIBase, specifically), and your are assigning to it each time you create a new button. Hence, you only have a reference to the last buttons.
You need an array of buttons. Let's see:
public class GUIBase extends JFrame {
public final int MAX_BUTTONS = 96;
private JButton[] buttons;
// ...
}
The next step is to create the array itself at the beginning:
public GUIBase() {
super("Minesweeper");
setLayout(new FlowLayout());
this.buttons = new JButton[MAX_BUTTONS];
//Fields
int position;
for (int i = 0; i < buttons.length; i++) {
position = (int) (Math.random() * 100);
this.buttons[ i ] = new JButton("R");
this.buttons[ i ].setToolTipText("Is this the correct one?");
this.add(this.buttons[ i ]);
Action action = new Action();
this.buttons[ i ].addActionListener(action);
}
}
You'll probably need more depth in arrays in order to completely understand the code. Basically, an array is a continuous collection of variables, which you can index by its position, from 0 to n-1, being n the number of positions.
Then you'll probably be able to fill the gaps yourself.
Hope this helps.
One part of your problems is coming from your action listener.
Of course, one part is that your code probably needs a list/array to keep track of all created buttons; but at least right now, you can rework your code without using arrays/list:
private class Action implements ActionListener {
public void actionPerformed(ActionEvent event) {
System.out.println("Somethin");
if (event.getSource() instanceofJButton) {
JBUtton clickedButton = (JButton) event.getSource();
String buttonText = clickedButton.getText();
if (buttonText.equals("R") ...
else if (buttonText.equals("F")
You see, the whole point here is: as of now, you just need to know what kind of button was created. And your ActionListener knows which button it was clicked on ...

Null Pointer with JButton Array

So far I have created a frame at adds my ControlPanel class, the class takes an int, and that int is used to fill an array with JButton objects which are the added to a Panel and displayed.
However I am getting a Null Pointer error when I try to add JButtons to the array. I'm not sure why (since I thought null pointers were from when you try to reference something that isn't in the spot in the array?)
Any help on this would be great appreciated.
Error Message:
Exception in thread "main" java.lang.NullPointerException
at elevator.ControlPanel.<init>(ControlPanel.java:22)
at elevator.Elevator_Simulator.main(Elevator_Simulator.java:27)
Main Class
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.event.*;
public class Elevator_Simulator extends JFrame {
public static void main(String[] args) {
JFrame frame = new JFrame ("Elevator Simulation");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new ControlPanel(8));
frame.pack();
frame.setVisible(true);
}
}
Control Panel Class:
import java.awt.Color;
import java.awt.event.*;
import javax.swing.*;
public class ControlPanel extends JPanel implements ActionListener {
public JButton[] floorButton; // an array of floor buttons.
public int[] floorIn; // state of button. 0 == not click >= 1 means clicked (how many times).
public ControlPanel(int x) {
JPanel floors = new JPanel();
for (int i = 0; i < x; i++) { // interates through user input and creates that many JButtons.
floorButton[i].add(new JButton("F" + Integer.toString(i))); // adds a button to button array. Sets text to F(floorNo).
floors.add(floorButton[i]); // adds buttons to the floor panel.
floorButton[i].addActionListener(this); // adds action listener to the buttons.
}
}
public void actionPerformed(ActionEvent e) {
for (int i = 0; i < floorButton.length; i++) {
if (e.getSource() == floorButton[i]) { // checks which button the event occured on.
floorButton[i].setBackground(Color.red); // sets button background to red.
floorButton[i].setText(floorButton[i].getText() + "(1)"); // marks button as clicked.
}
}
}
}
floorButton is not initalised to anything...
public JButton[] floorButton; // I'm null
public ControlPanel(int x) {
//...
for (int i = 0; i < x; i++) { // in
// Still null
floorButton[i].add(new JButton("F" + Integer.toString(i)));
Initalise the array to reflect what you need, also, don't use floorButton[i].add, you don't want to add the button to (what is currently a null element) button, you want to assign it to the position of the array...
public ControlPanel(int x) {
//...
floorButton = new JButton[x];
for (int i = 0; i < x; i++) { // in
floorButton[i] = new JButton("F" + Integer.toString(i));
I'm guessing you'll want to do the same with floorIn...
You have to initialize your floorButton.
floorButton = new JButton [yourCount];
You created the array of JButton, but you didn't create every element in the array. To do this:
Replace this:
floorButton[i].add(new JButton("F" + Integer.toString(i)));
by this:
floorButton[i] = new JButton("F" + Integer.toString(i));

find and replace dialog box

I'm trying to develop a Find and Replace like in Notepad. Here is my code so far for find. I am wondering how I can keep the dialog box open after pressing the button, so that I can use the dialog box for the next find.
import java.awt.BorderLayout;
import java.awt.event.*;
import java.io.FileInputStream;
import java.io.FileReader;
import java.util.Scanner;
import javax.swing.*;
class TextAreaEx extends JFrame implements ActionListener, KeyListener {
JButton button1;
JTextArea tx = new JTextArea();
int startFrom = 0;
int offset = 0;
String find = "";
String text = "";
TextAreaEx() {
super("My Frame");
FileInputStream fis = null;
StringBuffer sb = new StringBuffer();
try {
Scanner scan = new Scanner(new FileReader("C:\\Users\\Sam\\Desktop\\networktools.txt"));
while (scan.hasNext()) // while there's still something to read
{
tx.append(scan.nextLine() + "\n"); // append
}
} catch (Exception e) {
e.printStackTrace();
}
// text = sb.toString();
text = tx.getText();
text = text.toLowerCase();
button1 = new JButton("Find");
button1.addActionListener(this);
getContentPane().add(button1, BorderLayout.PAGE_START);
button1.setFocusable(false);
JScrollPane p1 = new JScrollPane(tx);
getContentPane().add(p1);
JFrame.setDefaultLookAndFeelDecorated(true);
tx.addKeyListener(this);
setSize(400, 400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocation(400, 300);
setVisible(true);
}
public static void main(String s[]) {
new TextAreaEx();
}
public void actionPerformed(ActionEvent e) {
startFrom = 0;
offset = 0;
if (e.getSource() == button1) {
find = (String) JOptionPane.showInputDialog(this, "FIND:\n", "Find", JOptionPane.INFORMATION_MESSAGE, null, null, null);
find = find.toLowerCase();
findWord();
this.setVisible(true);
}
}
public void findWord() {
offset = text.indexOf(find, startFrom);
if (offset > -1) {
tx.setFocusable(true);
tx.select(offset, find.length() + offset);
startFrom = find.length() + offset + 1;
} else {
JOptionPane.showMessageDialog(this, "No (more) matches");
}
}
public void keyPressed(KeyEvent ke) {
if (ke.getKeyCode() == KeyEvent.VK_F3) {
findWord();
}
}
public void keyReleased(KeyEvent ke) {
}
public void keyTyped(KeyEvent ke) {
}
}
Thanks for the help.
JOptionPane is meant to be used just to aks a simple question for the user to answer with yes/no, ok/cancel or ask the for simple input and than be closed.
"Real" find/replace dialog boxes need to do a lot more than this, don't try to use JOptionPane for this, it was not designed for that purpose.
You will need complete new dialog, (JFrame in you case) that can accomplish what you need, and you will be able to extend it to specify other options like "Match Case", use regular expressions and so on.
Notice: Aside from this your code needs A LOT of other improvements. Start with not using magic numbers and strings hard coded, name your variables appropriately ( and not button1 ) , stick up to the coding and formatting conventions in the language that you are using. Try to use smaller classes and methods that do just one thing - "A class should have one, and only one, reason to change". Try to extract to search functionality itself in its own class and write unit tests for it.
After time you could try to look at the some open source Java projects (JEdit is good example for editor) just to see how professional code looks like.
Good luck.

Categories