I'm fairly new with Java, (and this site) so I'm not sure what to do with this "issue"...
I'm not sure whether to put my entire code in this or not...So I'll just put what I think is causing the issue. The program compiles perfectly, except when I try to run it. That's when I get a Null Pointer Exception at line 96. I have no idea why this is happening.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
public class LicensePlateGeneratorTemplate extends JFrame implements ActionListener{
private JTextArea txtOutput;
private JTextField txtNumPlates;
private JButton btnDisplay;
private JLabel lblTitle, lblInstruction;
private PrintWriter output;
private String letters, numbers, fileName;
private int randomLetter, randomNumber, numPlates;
private String [] a, b ;
private String [] lttrArray, nmbrArray;
public static void main(String[] args) throws IOException{
new LicensePlateGeneratorTemplate();
}
public LicensePlateGeneratorTemplate() throws IOException{
//label thast contains number of licence plates generated
txtNumPlates = new JTextField();
txtNumPlates.setBounds(320, 60, 28, 28);
lblInstruction = new JLabel("How many license plates would you like to generate?");
lblInstruction.setBounds(15, 60, 300, 28);
//A random number generator in the action performed method should allow you to select a random letter from the letters String
//then a random number from the numbers String
String letters = "A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Z";
String numbers = "1,2,3,4,5,6,7,8,9,0";
lttrArray = letters.split (",");
nmbrArray = numbers.split (",");
System.out.println(lttrArray[20] + lttrArray [10]);
System.out.println(nmbrArray[3]+ nmbrArray [5]);
fileName = "licensePlates.txt";
output = new PrintWriter(new FileWriter(fileName));
lblTitle = new JLabel();
lblTitle.setFont(new Font("Britannic Bold", Font.BOLD, 28));
lblTitle.setText("License Plate Generator");
lblTitle.setBounds(30, 10, 400, 50);
JPanel panel = new JPanel();
panel.setLayout(null);
//JTextArea
txtOutput = new JTextArea();
txtOutput.setBounds(60, 150, 275, 196);
txtOutput.setEditable(true);
//generate button properties
btnDisplay = new JButton();
btnDisplay.setText("Generate");
btnDisplay.setBounds(150, 100, 100, 40);
btnDisplay.setFocusable(true);
btnDisplay.addActionListener(this);
//add components to the panel
panel.add(btnDisplay);
panel.add(txtOutput);
panel.add(lblTitle);
panel.add(lblInstruction);
panel.add(txtNumPlates);
//frame properties
setContentPane(panel);
setSize(400, 400);
setTitle("License Plate Generator");
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
setVisible(true);
}
public void actionPerformed (ActionEvent e)
{
if (e.getSource() == btnDisplay)
{
//change number user inputs into a int value
int userNum = Integer.parseInt(txtNumPlates.getText ());
for (int k = 0; k <= userNum; k ++)
{//number of licence places that are being made
for (int i = 0; i < 4; i ++)//loop for letters produced
{
int randLtr = 0 + (int)(Math.random() * ((24 - 0) + 1));
a [i] = lttrArray [randLtr];
output.println (a[i]);
txtOutput.insert(a[i] + "\n", 0);
}
for (int j = 0; j < 3; j++)//loop for number produced
{
int randNum = 0 + (int)(Math.random() * ((9 - 0) + 1));
b [j] = nmbrArray [randNum];
output.println (b[j]);
txtOutput.insert(b[j] + "\n", 0);
}
output.close();//closes fileWriter
}//end of userNum loop
}//end of e.getsource
}
}
Edit: Added full code.
Since lttrArray is clearly non-null (unless you're assigning it as lttrArray = null somewhere in the snipped code), I would guess that a is null.
Related
//*****
I stripped down as much as I thought possible while still being pleasing to use. this is my beginner calulator project. it shows result as I type. I'm using multiple textFields to achieve this. I'm open to smarter ways. for now though I would like to lie in my bed as I've made it to learn.
On fresh start up no issues with parsing and the getting a result but after clear lets say I used addButton last it will automatically add the first new number to itself then give me the result as the new num1. if I set num1 to 0; add works but not multiplication because of zero... is .setText(" "); really deleting the values? is there a better way? I've read all I could find on textFields.
I will happily take direction to the correct reading material in lieu of a direct answer. textField numbered slightly out of order. My apologies order is top down - 3 -2 -1 -4 -5. 4 and 5 are to help me visualize the problem 3 shows the work, 2 the result and 1 is used for parsing num1 and setting the current result to num1 so I can chain the addition.
I've tried parsing at different locations setting num1 to 0 setting result to the remainder of result and num1 to be the new num2.. and a bunch of other silly attempts at similar solulutions. I know that my if(numberButtons[i]) { statement directly above the switch for + - * / where it sets num2=Double.parseDouble(textField4.getText()); is the main cause but it is also the only way I know to give constant results as I type in my numbers.
I,ve tried more thought-out and many more arbitrary changes to my code trying to understand what's really going on and what's possible.
Afer 3 weeks I am embarrassed for myself. Thank you for your time. Again even just the right direction will help me very much. I do like and desire to solve the problem on my own. I am just truly out of my depth as I am 3 months into this a few hours a day in my time off of work. I truly enjoy it and would love to have a sense of closure and completion to this problem.
///*************
package test;
import javax.swing.*;
import javax.swing.border.BevelBorder;
import javax.swing.border.Border;
import javax.swing.border.LineBorder;
import javax.swing.border.SoftBevelBorder;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Calc1 implements ActionListener {
JFrame frame;
JTextField textField3,textField2,textField1,textField4,textField5;
JButton[] numberButtons = new JButton[10];
JButton[] functionButtons = new JButton[6];
JButton addButton,subButton,multiButton,diviButton,decimalButton;
JButton equalButton,deleteButton,clearButton,negativeButton;
JPanel panel;
JLabel label;
Font myFont = new Font("Monospaced", Font.BOLD,31);
Font font1 = new Font("Monospaced", Font.BOLD, 30);
Font font2 = new Font("Monospaced", Font.BOLD, 28);
Font font3 = new Font("SansSerif", Font.BOLD, 48);
Font font4 = new Font("Monospaced", Font.BOLD, 65);
double num1=0,num2=0,result=0;
char operator;
Calc1(){
Border border1 = new LineBorder(Color.DARK_GRAY, 4, true);
frame = new JFrame("Calculator");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(null);
frame.setOpacity(1);
frame.setVisible(true);
frame.setBounds(201, 60, 323, 700);
label = new JLabel();
label.setBounds(5, 4, 300, 52);
label.setFont(font1);
label.setVisible(true);
label.setText("Calculator");
label.setForeground(Color.blue);
label.setFont(new Font("Console", 1, 17));
label.setBorder(new SoftBevelBorder(BevelBorder.LOWERED));
Border border = new LineBorder(Color.LIGHT_GRAY, 7, true);
textField3 = new JTextField();
textField3.setBounds(5,54, 299, 38);
textField3.setFont(font2);
textField3.setBackground(Color.lightGray);
textField3.setBorder(border);
textField3.setOpaque(true);
textField3.setHorizontalAlignment(JTextField.RIGHT);
textField3.setFocusable(true);
textField2 = new JTextField();
textField2.setBounds(5, 89, 299, 44);
textField2.setFont(myFont);
textField2.setBackground(Color.lightGray);
textField2.setBorder(border);
textField2.setVisible(true);
textField2.setOpaque(true);
textField2.setHorizontalAlignment(JTextField.RIGHT);
textField2.setFocusable(false);
textField1 = new JTextField();
textField1.setBounds(5,510, 300, 35);
textField1.setFont(myFont);
textField1.setVisible(true);
textField4 = new JTextField();
textField4.setBounds(5,549, 300, 35);
textField4.setFont(myFont);
textField4.setVisible(true);
textField5 = new JTextField();
textField5.setBounds(5,580, 300, 35);
textField5.setFont(myFont);
textField5.setVisible(true);
addButton = new JButton("+");
subButton = new JButton("-");
multiButton = new JButton("x");
diviButton = new JButton("÷");
decimalButton = new JButton(".");
equalButton = new JButton("=");
deleteButton = new JButton("←");
clearButton = new JButton("AC");
functionButtons[0] = addButton;
functionButtons[1] = subButton;
functionButtons[2] = multiButton;
functionButtons[3] = diviButton;
functionButtons[4] = decimalButton;
functionButtons[5] = clearButton;
for(int i=0; i<6; i++) {
functionButtons[i].addActionListener(this);
functionButtons[i].setFont(myFont);
functionButtons[i].setFocusable(false);
functionButtons[i].setBorder(new SoftBevelBorder(BevelBorder.RAISED));
}
for(int i=0; i<10; i++) {
numberButtons[i] = new JButton(String.valueOf(i));
numberButtons[i].addActionListener(this);
numberButtons[i].setFont(font2);
numberButtons[i].setFocusable(false);
}
panel = new JPanel();
panel.setLayout(new GridLayout(4,4,4,4));
panel.add(label);
panel.setBackground(Color.DARK_GRAY);
panel.setForeground(Color.BLACK);
panel.setVisible(true);
panel.setOpaque(true);
panel.setBorder(border1);
panel.setBounds(4, 133, 300, 300);
panel.add(numberButtons[7]);
panel.add(numberButtons[8]);
panel.add(numberButtons[9]);
panel.add(addButton);
panel.add(numberButtons[4]);
panel.add(numberButtons[5]);
panel.add(numberButtons[6]);
panel.add(subButton);
panel.add(numberButtons[1]);
panel.add(numberButtons[2]);
panel.add(numberButtons[3]);
panel.add(multiButton);
panel.add(decimalButton);
panel.add(numberButtons[0]);
panel.add(clearButton);
panel.add(diviButton);
frame.add(panel);
frame.add(label);
frame.add(textField3);
frame.add(textField2);
frame.add(textField1);
frame.add(textField4);
frame.add(textField5);
frame.setOpacity(1);
frame.setForeground(Color.BLACK);
frame.setBackground(Color.BLACK);
frame.setVisible(true);
label.setForeground(Color.blue);
label.setBackground(Color.GRAY);
label.setOpaque(true);
}
public static void main(String[] args) {
Calc1 calc = new Calc1();
}
public void actionPerformed(ActionEvent e) {
for(int i=0; i<10; i++) {
if(e.getSource() == numberButtons[i]) {
textField1.setText(textField1.getText().concat(String.valueOf((i))));
textField3.setText(textField3.getText().concat(String.valueOf((i))));
textField4.setText(textField4.getText().concat(String.valueOf((i))));
textField5.setText(textField5.getText().concat(String.valueOf((i))));
}
}
if (e.getSource()==subButton) {
num1=Double.parseDouble(textField1.getText());
operator='-';
textField3.setText(textField3.getText().concat("-"));
textField4.setText("");
textField4.setText(textField4.getText().concat(""));
}
if (e.getSource()==addButton) {
num1 = Double.parseDouble(textField1.getText());
operator = '+';
textField3.setText(textField3.getText().concat("+"));
textField4.setText("");
textField4.setText(textField4.getText().concat(""));
}
if (e.getSource()==multiButton) {
num1 = Double.parseDouble(textField1.getText());
operator = '*';
textField3.setText(textField3.getText().concat("x"));
textField4.setText("");
textField4.setText(textField4.getText().concat(""));
}
if (e.getSource()==diviButton) {
num1 = Double.parseDouble(textField1.getText());
operator = '/';
textField3.setText(textField3.getText().concat("÷"));
textField4.setText("");
textField4.setText(textField4.getText().concat(""));
}
for(int i=0; i<10; i++) {
if(e.getSource()==numberButtons[i]) {
num2=Double.parseDouble(textField4.getText());
switch(operator) {
case'-':
result=num1-num2;
textField1.setText(String.valueOf(result));
textField5.setText(String.valueOf(num1));
break;
case'+':
result=num1+num2;
textField1.setText(String.valueOf(result));
textField5.setText(String.valueOf(num1));
break;
case'*':
result=num1*num2;
textField1.setText(String.valueOf(result));
textField5.setText(String.valueOf(num1));
break;
case'/':
result=num1/num2;
textField1.setText(String.valueOf(result));
textField5.setText(String.valueOf(num1));
break;
}
}
textField2.setText(String.valueOf((result)));
}
if (e.getSource()==clearButton) {
textField3.setText("");
textField2.setText("");
textField1.setText("");
textField4.setText("");
textField5.setText("");
}
}
}
Where you clear all your JTextFields, You should also reset all member variables used in previous calculations. After all, beacause of their scope (class global), they will still be holding values unless reset:
if (e.getSource() == clearButton) {
textField3.setText("");
textField2.setText("");
textField1.setText("");
textField4.setText("");
textField5.setText("");
num1 = 0;
num2 = 0;
result = 0;
operator = '\0';
}
New programmer here, I have been working for a few days on this bit of code that is meant to create a UI where I input a basement's perimeter length (textfield integer), if a new pump is needed (combobox string), if there is an outlet nearby (combobox string), and how many hours It will take to prepare a site (textfield integer), and I calculate my costs to complete a job. I was able to set up a UI where I can enter the inputs and press a button to calculate but I'm having trouble connecting the button I made to the formula I made to generate a price. Here is my code:
package packagepackage;
import packagepackage.HintTextFieldUI;
import java.awt.*;
import java.awt.BorderLayout;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class CP_GUI implements ActionListener {
String[] sumpo = {"New sump pump","Existing sump pump"};
String[] electo = {"There is an outlet within 6 feet of sump pump","There is no outlet nearby, or I do not need a new one"};
Integer estimatex = 0;
String esto = String.valueOf(estimatex);
public volatile String estimatoof = "Estimated Cost: ${}".format(esto);
private JComboBox sump = new JComboBox(sumpo);
private JComboBox elec = new JComboBox(electo);
private JTextField linear = new JTextField();
private JTextField prep = new JTextField();
private JLabel title = new JLabel("Drain Tile Calculator");
private JButton calculate = new JButton("Calculate!");
public JLabel estimate = new JLabel(estimatoof);
private JFrame frame = new JFrame();
private JPanel panel = new JPanel();
public CP_GUI() {
linear.addActionListener(this);
calculate.addActionListener(this);
elec.addActionListener(this);
sump.addActionListener(this);
prep.addActionListener(this);
// the panel with the button and text
JPanel panel = new JPanel();
panel.setBorder(BorderFactory.createEmptyBorder(400, 400, 100, 100));
panel.setLayout(new GridLayout(0, 1));
panel.add(linear);
panel.add(sump);
panel.add(elec);
panel.add(prep);
frame.add(panel, BorderLayout.CENTER);
panel.add(title);
calculate.addActionListener(this);
panel.add(calculate);
// set up the frame and display it
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("Drain Tile Calculator");
frame.pack();
frame.setVisible(true);
linear.setUI(new HintTextFieldUI("Perimeter length", true));
prep.setUI(new HintTextFieldUI("Hours of preptime", true));}
// create one Frame
public static void main(String[] args) {
new CP_GUI();
}
#Override
public void actionPerformed(ActionEvent e){
// TODO Auto-generated method stub
if(e.getSource()==linear) {String input = linear.getText();
Integer pars = Integer.parseInt(input);
Integer distVar = pars *= 13;
estimatex += distVar;
} else if (e.getSource()==sump) {String inputa = sump.getToolTipText();
int sumpa = 0;
if(inputa == "New sump pump" | inputa == "yes") {
sumpa += 260;}
estimatex += sumpa;
} else if (e.getSource()==elec) {String inputb =elec.getToolTipText();
int eleca = 0;
if("There is an outlet within 6 feet of the sump pump".equals(inputb)) {
eleca += 1;
}
eleca *= 280;
estimatex += eleca;
}
else if (e.getSource()==prep) {String inputc = prep.getText();
int parsa = Integer.parseInt(inputc);
int prepCost = parsa += 1;
prepCost *= 110;
estimatex += prepCost;
} else if (e.getSource()==linear) {
String disto = linear.getText();
int di = Integer.parseInt(disto);
di *= 13;
String pumpo = (String)sump.getSelectedItem();
int sumpo = 0;
if ("New sump pump".equals(pumpo)) {
sumpo += 260;
}
String ele = (String)elec.getSelectedItem();
int elc = Integer.parseInt(ele);
elc *= 280;
String clea = prep.getText();
int cla = Integer.parseInt(clea);
cla += 1;
cla *= 110;
int cali = 0;
cali += di;
cali += sumpo;
cali += elc;
cali += cla;
estimatex = cali;
}
}
}
Edit: Made the suggested edits made so far and now the UI opens and works, the only issue is that the estimated price does not show up. Am I connecting the action listener correctly?
Your "primary" problem is right here...
String disto = String.valueOf(linear);
where linear is a JTextField, so the above call will generate something like...
javax.swing.JTextField[,0,0,0x0,invalid,layout=javax.swing.plaf.basic.BasicTextUI$UpdateHandler,alignmentX=0.0,alignmentY=0.0,border=com.apple.laf.AquaTextFieldBorder#4e323305,flags=288,maximumSize=,minimumSize=,preferredSize=,caretColor=javax.swing.plaf.ColorUIResource[r=0,g=0,b=0],disabledTextColor=javax.swing.plaf.ColorUIResource[r=128,g=128,b=128],editable=true,margin=javax.swing.plaf.InsetsUIResource[top=0,left=0,bottom=0,right=0],selectedTextColor=com.apple.laf.AquaImageFactory$SystemColorProxy[r=0,g=0,b=0],selectionColor=com.apple.laf.AquaImageFactory$SystemColorProxy[r=165,g=205,b=255],columns=0,columnWidth=0,command=,horizontalAlignment=LEADING]
which is obviously not what you're looking for.
You should probably be just doing something like...
String disto = linear.getText();
pumpo == "New sump pump" is also not how you compare a String in Java, you should be using "New sump pump".equals(pumpo) ... but I suspect you're going to have the same issues as mentioned above.
I really recommend you take the time to read through Creating a GUI With Swing as well as taking the time to come to grips with the core basics of the language
I want to add a JComboBox to my main panel and fill it with an ArrayList I made in a different method named rectSizeList (which right now prints the ArrayList to the console), this method gets its parameters from another static method named actionPerformed. I cant figure a way to take the filled array after user input to fill my ComboBox. Any help will be appreciated.
All comment is this format are to aid question:
/*
* Like so
*
*/
All other comments are to help whomever my want to compile and run, so that they might understand what is going on.
Main class
import javax.swing.*;
public class ductulatorApp
{
public static void main(String[] args)
{
JFrame frame = new DuctulatorFrame();
frame.setVisible(true);
}
}
Frame class
import javax.swing.*;
import java.awt.*;
public class DuctulatorFrame extends JFrame
{
private static final long serialVersionUID = 1L;
public DuctulatorFrame()
{
setTitle("Test Scores");
setSize(267, 200);
centerWindow(this);
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new DuctulatorPanel();
this.add(panel);
}
private void centerWindow(Window w)
{
Toolkit tk = Toolkit.getDefaultToolkit();
Dimension d = tk.getScreenSize();
setLocation((d.width-w.getWidth())/2, (d.height-w.getHeight())/2);
}
}
Panel class
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.text.*;
import java.util.ArrayList;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class DuctulatorPanel extends JPanel implements ActionListener
{
private static final long serialVersionUID = 1L;
private JTextField staticTextField,
cfmTextField,
rductTextField,
sqductTextField;
private JLabel staticLabel,
cfmLabel,
rductLabel,
sqductLabel;
private JButton calculateButton,
exitButton,
clearButton;
private JComboBox ductSizes; //JComboBox instance
private String[] ductList; //Array to fill JComboBox
double staticP; //static pressure entered by user
double cfm; //cfm entered by user
double deSQ;
double de; //round duct diameter
double pi = 3.14;
double ca; //round duct surface area
double radious;
double sqrA; //rectangular duct area
//two sides of rectangular duct
double a = 4;
double b = 4;
String squareduct;
public DuctulatorPanel()
{
// Creates main panel for labels and text fields
JPanel displayPanel = new JPanel();
displayPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
staticLabel = new JLabel("Static pressure:");
displayPanel.add(staticLabel);
staticTextField = new JTextField(10);
displayPanel.add(staticTextField);
cfmLabel = new JLabel(" CFM:");
displayPanel.add(cfmLabel);
cfmTextField = new JTextField(10);
displayPanel.add(cfmTextField);
rductLabel = new JLabel("Round Duct:");
displayPanel.add(rductLabel);
rductTextField = new JTextField(15);
rductTextField.setEditable(false);
rductTextField.setFocusable(false);
displayPanel.add(rductTextField);
sqductLabel = new JLabel("Square Duct:");
displayPanel.add(sqductLabel);
/*
* This is where I want to add my JComboBox problem is I want to populate ductList arr
* with the array inside rectSizeList(int number) BELOW
* right now this method only prints my array to the console
* this method takes its parameters from the value assigned to
* actionperformed(ActionEvent e)
* below is comboBox commented out
*/
//ductList = new String[list.size]; THIS IS ASSUMING I COULD SOME HOW TRANSFER
//ductList = list.toArray(ductList); ARRAYLIST UP HERE AND NAME IT LIST AND USE IT
//ductSizes = new JComboBox(ductList);
//ductSizes.setSelectedIndex(1);
//displayPanel.add(ductSizes);
sqductTextField = new JTextField(10);
sqductTextField.setEditable(false);
sqductTextField.setFocusable(false);
displayPanel.add(sqductTextField);
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
calculateButton = new JButton("Calculate");
calculateButton.addActionListener(this);
buttonPanel.add(calculateButton);
clearButton = new JButton("Clear");
clearButton.addActionListener(this);
buttonPanel.add(clearButton);
exitButton = new JButton("Exit");
exitButton.addActionListener(this);
buttonPanel.add(exitButton);
this.setLayout(new BorderLayout());
this.add(displayPanel, BorderLayout.CENTER);
this.add(buttonPanel, BorderLayout.SOUTH);
}
public void actionPerformed(ActionEvent e)
{
NumberFormat number = NumberFormat.getNumberInstance();
number.setMaximumFractionDigits(1);
Object source = e.getSource();
if(source == exitButton)System.exit(0);
else if(source == clearButton)
{
staticTextField.setText("");
cfmTextField.setText("");
rductTextField.setText("");
sqductTextField.setText("");
staticP = 0;
cfm = 0;
deSQ = 0;
}
else if(source == calculateButton)
{
try
{
staticP = Double.parseDouble(staticTextField.getText());
cfm = Double.parseDouble(cfmTextField.getText());
}
catch(NumberFormatException nfe)
{
staticTextField.setText("Invalid input");
staticP = 0;
cfm = 0;
deSQ = 0;
de = 0;
}
deSQ = staticP * (0.109136 * Math.pow(cfm, 1.9)); //Calculate round duct
de = Math.pow(deSQ, 0.199) * 2.5; //diameter
// Calculate round duct surface area
radious = de/2;
ca = (radious * radious) * pi;
ca = (int)ca;
rectSizeList((int)ca);
double i = 0;
for(i=0; i<ca; i++)
{
a = a + 0.5;
b = b + 0.5;
i = a * b; // convert round duct to rectangular duct
}
sqrA = i;
a = (int)a;
b = (int)b;
rductTextField.setText(number.format(de));
squareduct = (a + " x " + b);
sqductTextField.setText(squareduct);
}
}
public ArrayList<String> rectSizeList(int number)
{
if (number <= 0) throw new IllegalArgumentException("The number should be greater than 0.");
int i = 0;
int j = 0;
/*
* This is the array list I am hoping to use in order to fill array for
* comboBox
*/
ArrayList<String> rectangularDucts = new ArrayList<String>(); //Create array for rectangular duct
// Fill array for rectangular duct using nested for loop
/*
* If statement will ensure the result is with in range of surface
* area of duct
*/
for(i=4; i<=50; i++)
{
for(j=4; j<=50; j++)
{
if(number == i*j || (i*j)+1 == number || (i*j)-2 == number)
{
rectangularDucts.add(i + " x " + j);
}
}
if(number == i*j || (i*j)+1 == number || (i*j)-2 == number)
{
rectangularDucts.add(i + " x " + j);
}
}
System.out.println(rectangularDucts);
return rectangularDucts;
}
}
I think that your problem is easily solved with just a DefaultComboBoxModel object, or in your situation (I guess), a DefaultComboBoxModel<String> object. Give your class this field, create your JComboBox with this as its model, by passing it into the constructor, and then fill this model object as the need arises.
For example:
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.*;
public class ComboModelEg extends JPanel {
private DefaultComboBoxModel<String> comboModel = new DefaultComboBoxModel<>();
private JComboBox<String> comboBox = new JComboBox<>(comboModel);
private JTextField textField = new JTextField(5);
public ComboModelEg() {
// so combo box is wide enough
comboBox.setPrototypeDisplayValue(" ");
add(comboBox);
add(textField);
add(new JButton(new AddToComboAction("Add Text", KeyEvent.VK_A)));
}
// AbstractAction is like a *super* ActionListener
private class AddToComboAction extends AbstractAction {
public AddToComboAction(String name, int mnemonic) {
super(name); // button's text
putValue(MNEMONIC_KEY, mnemonic); // button's mnemonic key
}
#Override
public void actionPerformed(ActionEvent e) {
String text = textField.getText(); //get text from text field
comboModel.addElement(text); // and put it into combo box's model
}
}
private static void createAndShowGui() {
ComboModelEg mainPanel = new ComboModelEg();
JFrame frame = new JFrame("ComboModelEg");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
Translated to your code, it could look something like:
for (i = 4; i <= 50; i++) {
for (j = 4; j <= 50; j++) {
if (number == i * j || (i * j) + 1 == number
|| (i * j) - 2 == number) {
// rectangularDucts.add(i + " x " + j); //!!
comboModel.addElement(i + " x " + j); //!!
}
}
if (number == i * j || (i * j) + 1 == number || (i * j) - 2 == number) {
// rectangularDucts.add(i + " x " + j);
comboModel.addElement(i + " x " + j); //!!
}
}
this is how i do it
ArrayList<String> myList = new ArrayList<>();
//some code to populate the list
jComboBox.removeAllItems();
for(int i=0;i<myList.size();i++){
jComboBox.addItem(myList.get(i));
}
I was able to program this, and I don't have any errors that I can see, and it even displays the gui. I'm pretty sure I assigned the buttons properly. But the GUI is temperamental, and when I run it, it displays but sometimes the insides of the gui disappear when I enter values. But it calculates nCr, just not pCr.
I have a driver class. Pretty sure it's implemented properly. Here's my panel class. I'm wondering what's wrong and why the GUI doesn't function properly
I realize this is a lot of code. I'm not expecting anyone to rewrite this for me. I just want to know what I'm doing wrong, and how I can go about correcting it.
Thanks.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.Color;
import javax.swing.JOptionPane;
public class PermCombCalc extends JPanel {
JButton permButton = new JButton();
JButton combButton = new JButton();
JButton clearButton = new JButton();
JTextField npermField = new JTextField();
JTextField rperField = new JTextField();
JTextField nchooseField = new JTextField();
JTextField rchooseField = new JTextField();
JTextField pAnswerField = new JTextField();
JTextField cAnswerField = new JTextField();
public PermCombCalc() {
setLayout(new BorderLayout());
setPreferredSize(new Dimension(1000, 700));
JLabel permLabel = new JLabel("Permutation:");
permLabel.setBounds(10, 20, 100, 20);
permLabel.setForeground(Color.BLACK);
add(permLabel);
JLabel combLabel = new JLabel("Combination:");
combLabel.setBounds(215, 20, 75, 20);
combLabel.setForeground(Color.BLACK);
add(combLabel);
// Creating Permutation Button
JLabel PnrLabel = new JLabel("P (n,r)");
PnrLabel.setForeground(Color.black);
permButton.setBounds(10, 115, 100, 25);
add(permButton);
permButton.add(PnrLabel);
// Action Listener for permbutton
permButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
permButton.setActionCommand("Perm");
permButton.addActionListener(new ButtonListener());
}
});
// Creating combination button
JLabel CnrLabel = new JLabel("C(n, r)");
CnrLabel.setForeground(Color.black);
combButton.setBounds(190, 115, 100, 25);
add(combButton);
combButton.add(CnrLabel);
// ActionListener
combButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
combButton.setActionCommand("comb");
combButton.addActionListener(new ButtonListener());
}
});
// Text fields for n and r
npermField.setBounds(23, 50, 60, 20);
add(npermField);
nchooseField.setBounds(230, 50, 60, 20);
add(nchooseField);
rperField.setBounds(23, 80, 60, 20);
add(rperField);
rchooseField.setBounds(230, 80, 60, 20);
add(rchooseField);
// Input fields
JLabel npLabel = new JLabel("n:");
npLabel.setForeground(Color.black);
npLabel.setBounds(10, 55, 10, 10);
add(npLabel);
JLabel ncLabel = new JLabel("n:");
ncLabel.setForeground(Color.BLACK);
ncLabel.setBounds(217, 55, 10, 10);
add(ncLabel);
JLabel rpLabel = new JLabel("r:");
rpLabel.setForeground(Color.BLACK);
rpLabel.setBounds(10, 85, 10, 10);
add(rpLabel);
JLabel rcLabel = new JLabel("r:");
rcLabel.setForeground(Color.BLACK);
rcLabel.setBounds(217, 85, 10, 10);
add(rcLabel);
// Fields for answers
JLabel pAnswerJLabel = new JLabel("<-Answers->");
pAnswerJLabel.setForeground(Color.BLACK);
pAnswerJLabel.setBounds(115, 155, 74, 10);
add(pAnswerJLabel);
pAnswerField.setBounds(10, 150, 100, 20);
add(pAnswerField);
cAnswerField.setBounds(190, 150, 100, 20); // where is this field?!
add(cAnswerField);
// Buttons
//clearButton.setBounds(10, 210, 110, 25);
//add(clearButton);
//JLabel clearLabel = new JLabel("Clear Fields");
//clearLabel.setForeground(Color.BLACK);
//clearButton.add(clearLabel);
// clearButton.addActionListener(new ActionListener() {
// public void actionPerformed(ActionEvent e) {
// clearButton.setActionCommand("Clear");
}
private class ButtonListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("perm")) {
// contentPane.setBackground(Color.red);
long Pnr = Permutation();
if (Pnr != 0) {
pAnswerField.setText(Pnr + "");
}
} else if (e.getActionCommand().equals("comb")) {
// contentPane.setBackground(Color.black);
long Cnr = Combination();
if (Cnr != 0) {
cAnswerField.setText(Cnr + "");
}
} else if (e.getActionCommand().equals("Clear")) {
// contentPane.setBackground(Color.lightGray);
npermField.setText(null);
rperField.setText(null);
pAnswerField.setText(null);
nchooseField.setText(null);
rchooseField.setText(null);
cAnswerField.setText(null);
}
}
public long Permutation() {
String npString = npermField.getText();
String rpString = rperField.getText();
int npint = 0;
int rpint = 0;
try {
npint = Integer.parseInt(npString);
rpint = Integer.parseInt(rpString);
} catch (NumberFormatException e) {
JOptionPane.showMessageDialog(null,"ERROR! The values for 'n' and 'r' \n must be positive integers");
return 0;
}
if (npint <= 0 || rpint <= 0) {
JOptionPane.showMessageDialog(null,"ERROR! The values for 'n' and 'r' \n must be positive integers");
return 0;
}
if (npint < rpint) {
JOptionPane.showMessageDialog(null,"ERROR! The value of 'r' must be less than \n or equal to the value of 'n.'");
return 0;
}
long Pnr = 1;
int mult = npint;
int nmr = (npint - rpint);
while (mult > nmr) {
Pnr = Pnr * mult;
mult--;
}
return Pnr;
}
public long Combination() {
String ncString = nchooseField.getText();
String rcString = rchooseField.getText();
int ncint = 0;
int rcint = 0;
try {
ncint = Integer.parseInt(ncString);
rcint = Integer.parseInt(rcString);
} catch (NumberFormatException e) {
JOptionPane.showMessageDialog(null,"ERROR! The values for 'n' and 'r' \n must be positive integers");
return 0;
}
if (ncint <= 0 || rcint <= 0) {
JOptionPane.showMessageDialog(null,"Error! The values for 'n' and 'r' \n must be positive integers");
return 0;
}
if (ncint < rcint) {
JOptionPane.showMessageDialog(null,"ERROR! The value of 'r' must be less than \n or equal to the value of 'n.'");
return 0;
}
long nfact = 1;
for (int i = 2; i <= ncint; i++) {
nfact = nfact * i;
}
long rfact = 1;
for (int i = 2; i <= rcint; i++) {
rfact = rfact * i;
}
long nmr = ncint - rcint;
int nmrfact = 1;
for (int i = 2; i <= nmr; i++) {
nmrfact = nmrfact * i;
}
long Cnr = (nfact / (rfact * nmrfact));
return Cnr;
}
}
}
You are using BorderLayout, but you aren't actually specifying the placements of your components, so they are being rendered in unexpected places.
Here is a screenshot of your application with an orange border around pAnswerField and a red border around cAnswerField
You should take a look at the A Visual Guide to Layout Managers for help on using the Layout Managers properly.
For your application, GridLayout is probably a resonable balance between complexity and layout flexibility
GridBagLayout or SpringLayout will give you the most flexibility, but they can be frustratingly complex to work with.
EDIT Another minor problem which is causing the permButton to misbehave.
In your button creation code you have:
permButton.setActionCommand("Perm");
In your action listener you have: if (e.getActionCommand().equals("perm"))
As written your ActionListener will never get invoked when permButton gets pressed... Either switch to equalsIgnoreCase or define a constant rather than using string literals.
I find adding colored borders to be very helpful when doing layout work. Here's a quick example of how to do this:
npermField.setBounds(23, 50, 60, 20);
add(npermField);
nchooseField.setBounds(230, 50, 60, 20);
// add a border to make the component easier to see during layout.
npermField.setBorder(BorderFactory.createLineBorder(Color.ORANGE));
add(nchooseField);
If you like your ButtonListener class the way it is (I don't; will comment about it after the main issue), you can simply reword the buttons' setup:
.
.
.
add(permButton);
permButton.add(PnrLabel);
// Action Listener for permbutton
permButton.setActionCommand("Perm");
permButton.addActionListener(new ButtonListener());
.
.
.
(and likewise for the other buttons).
See? There is no need to add an ActionListener more than once AND also no need to add an ActionListener in order to add the real ActionListener.
The way your application was:
it didn't work on the first button press (since only then the correct listener is set up);
after the first button press, each new press would add another listener, eventually producing unexpected results (I didn't analyzed it thoroughly, and frankly I will not).
About the ButtonListener
Roughly speaking, your class does:
if (typeA) {
doActionA();
} else if (typeB) {
doActionB();
} else if (typeC) {
doActionC();
}
You could simply create 3 separate ActionListeners, each doing just one thing (either doActionA(), or B or C), without ifs. Then set up each button with only the appropriate ActionListener. This way you could also remove the lines setActionCommand(type);, since they would become useless.
Basically, my problem is that I am not sure on how to set unlimited input arrays from user..
For now, the calculation only goes well if the user enters 6 subject exactly, but not if entered subject is less or more than 6..
Somehow, i want to make the input to be unlimited..
This is what I have so far:
THE MAIN CLASS
import javax.swing.*;
public class CGPAMain extends JFrame
{
public static void main(String[] args)
{
JFrame frame = new JFrame("GPA Calculation");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
MainPage panel = new MainPage();
frame.getContentPane().add(panel);
frame.pack();
frame.setVisible(true);
}
}
THE OTHER CLASS
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class MainPage extends JPanel
{
//declare GUI elements
private JLabel subjectLabel, cHoursLabel, gradeLabel;
private JTextField subject, cHours;
private JButton addSubjectButton, calcGPAButton, clearAllButton;
private JTextArea tArea;
private JComboBox grade;
//declare array to store and collect user input value
String[] subjectArray = new String[6];
String[] gradeArray = new String[6];
int[] cHoursArray = new int[6];
double[] gradeValue = { 4.00, 3.67, 3.33, 3.00, 2.67, 2.33, 2.00, 1.67, 1.33, 1.00, 0.00 };
String[] gradeLetter= { "A", "A-", "B+", "B", "B-", "C+", "C", "D", "D-", "E", "F"};
public MainPage()
{
setLayout (null);
setPreferredSize (new Dimension(500, 500));
setBackground (Color.orange);
//Properties of GUI elements
subjectLabel = new JLabel ("Subject Name: ");
subject = new JTextField (33);
subject.addActionListener (new TempListener());
gradeLabel = new JLabel ("Grade: ");
grade = new JComboBox (gradeLetter);
grade.addActionListener (new TempListener());
cHoursLabel = new JLabel ("Credit Hours: ");
cHours = new JTextField (1);
cHours.addActionListener (new TempListener());
addSubjectButton = new JButton("Add Another Subject");
addSubjectButton.addActionListener(new TempListener());
calcGPAButton = new JButton("Calculate GPA");
calcGPAButton.addActionListener(new TempListener());
clearAllButton = new JButton("Clear All");
clearAllButton.addActionListener(new TempListener());
tArea = new JTextArea(5, 5);
tArea.setEditable(false);
add (subjectLabel);
add (subject);
add (gradeLabel);
add (grade);
add (cHoursLabel);
add (cHours);
add (addSubjectButton);
add (calcGPAButton);
add (clearAllButton);
add (tArea);
//Position of GUI elements
subjectLabel.setBounds (20, 20, 150, 20);
subject.setBounds (120, 20, 350, 20);
gradeLabel.setBounds (20, 50, 50, 20);
grade.setBounds (120, 50, 50, 20);
cHoursLabel.setBounds (20, 80, 100, 20);
cHours.setBounds (120, 80, 50, 20);
addSubjectButton.setBounds (20, 120, 200, 30);
calcGPAButton.setBounds (300, 440, 175, 30);
clearAllButton.setBounds (20, 440, 120, 30);
tArea.setBounds (20, 170, 450, 250);
}
private class TempListener implements ActionListener
{
//---------------------------------------------------------------------------
// Performs the conversion when the enter key is pressed in the text field.
//---------------------------------------------------------------------------
double tCrPoints = 0.00, tCrHours = 0.00, tGPA = 0.00;
String status;
public void actionPerformed(ActionEvent event)
{
if (event.getSource() == addSubjectButton)
{
for (int i=0; i<6; i++)
{
subjectArray[i] = subject.getText();
gradeArray[i] = (String) grade.getSelectedItem();
cHoursArray[i] = Integer.parseInt(cHours.getText());
}
tArea.append (subject.getText() + "\t\t\t" +
grade.getSelectedItem() + "\t" +
cHours.getText() + "\n");
subject.setText("");
cHours.setText("");
}
if (event.getSource() == calcGPAButton)
{
for (int i=0 ; i<gradeArray.length; i++)
{
for (int j=0; j<gradeLetter.length; j++)
{
if(gradeArray[i].equals(gradeLetter[j]))
{
tCrHours += cHoursArray[i];
tCrPoints += gradeValue[j] * cHoursArray[i];
}
}
}
tGPA = tCrPoints/tCrHours;
if (tGPA >= 2)
status = ("Pass");
else
status = ("Fail");
//Output for text area
tArea.setText("Total Credit Points : " + tCrPoints + "\n" +
"Total Credit Hours : " + tCrHours + "\n\n" +
"Grade Point Average (GPA) : " + tGPA + "\n" +
"Status : " + status);
}
if (event.getSource() == clearAllButton)
{
tArea.setText("");
cHours.setText("");
grade.setSelectedIndex(0);
tCrHours = 0.00;
tCrPoints = 0.00;
}
}
}
}
You're looking for ArrayList<E>
You did a good job splitting apart the main() from the GUI and the rest of the application, but I think you should have taken it further to split the GUI from the calculation code, too.
Consider the larger question: Why does a GUI JPanel know about grades and GPAs? The job of a JPanel is to know how to render GUI elements within a box and route input events to the right widget object.
I believe your code would be far more maintainable and definitely more malleable if you split the code to manage the grades from the code to handle the GUI. There's always going to be a bit of a rough edge between telling the GUI to update values into the model vs having the model poll the data values from the GUI, but you can define that interface to suit your needs best: it might be a GPA object that uses SLaks's recommended ArrayList<E> to store individual Subject objects that know the name, grade, dates the course was conducted, etc. (It might just be (name, grade) tuples, since this is short and sweet so far.)
Your GPA object could export an interface: public void addSubject(String className, String grade) and public double getGPA(). Your GUI could call into this interface to add new classes and retrieve the GPA for display.
I realize that this is a much more drastic re-write than you were looking for. And it doesn't even immediately address your concern. But I believe the GPA code, when viewed on its own, would look far more easily manipulated than it currently does buried amongst the GUI code.
You should look at ArrayList, Vector or even LinkedList for the functionality you seek. Here's a tutorial explaining how to use an ArrayList.
The idea is simple: the ArrayList will take care of growing an internal array for storing its elements, and as you keep adding elements to it, it will keep growing automatically to accommodate them. Strictly speaking, the size won't be unlimited, but a maximum of 2^31-1 positions (assuming that you have enough memory) should me more than enough for most practical cases.
EDIT :
For your particular example:
// create an ArrayList
ArrayList<Double> gradeValue = new ArrayList<Double>();
// add elements to the ArrayList
gradeValue.add(4.00);
gradeValue.add(3.67); // etc.
// iterating over the ArrayList
for (int i = 0; i < gradeValue.size(); i++) {
double value = gradeValue.get(i);
// etc.
}
Use a hashmap to contain all your grades, and use array lists to contain your hour and grade earned. Here is a quick rewrite of what you have.
public class MainPage extends JPanel {
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
private JLabel subjectLabel, cHoursLabel, gradeLabel;
private JTextField subject, cHours;
private JButton addSubjectButton, calcGPAButton, clearAllButton;
private JTextArea tArea;
private JComboBox grade;
List<String> gradeArray = new ArrayList<String>();
List<Integer> cHoursArray = new ArrayList<Integer>();
Map<String, Double> grades = new HashMap<String, Double>();
public MainPage() {
this.populateGrades();
setLayout(null);
setPreferredSize (new Dimension(500, 500));
setBackground (Color.orange);
subjectLabel = new JLabel ("Subject Name: ");
subject = new JTextField (33);
subject.addActionListener (new TempListener());
gradeLabel = new JLabel ("Grade: ");
grade = new JComboBox (grades.keySet().toArray());
grade.addActionListener (new TempListener());
// ... THE REST OF YOU CODE ... //
}
private void populateGrades() {
grades.put("A", 4.00);
grades.put("A-", 3.67);
grades.put("B+", 3.67);
grades.put("B", 3.67);
grades.put("B-", 3.67);
grades.put("C+", 3.67);
grades.put("C", 3.67);
grades.put("D", 3.67);
grades.put("D-", 3.67);
grades.put("E", 3.67);
grades.put("F", 3.67);
}
private class TempListener implements ActionListener {
double tCrPoints = 0.00, tCrHours = 0.00, tGPA = 0.00;
String status;
public void actionPerformed(ActionEvent event) {
if (event.getSource() == addSubjectButton) {
// Not sure what you are trying to do here, you are basically setting the 3 arrays identical
// subject.getText() = 1 ==> subjectArray[1,1,1,1,1,1]
// Do not see the point of this at all
/* for (int i=0; i<6; i++) {
subjectArray[i] = subject.getText();
gradeArray[i] = (String) grade.getSelectedItem();
cHoursArray[i] = Integer.parseInt(cHours.getText());
} */
gradeArray.add(grade.getSelectedItem().toString());
cHoursArray.add(Integer.parseInt(cHours.getText()));
tArea.append (subject.getText() + "\t\t\t" + grade.getSelectedItem() + "\t" + cHours.getText() + "\n");
subject.setText("");
cHours.setText("");
}
if (event.getSource() == calcGPAButton) {
for (String grade : gradeArray) {
tCrPoints += grades.get(grade);
}
for (Integer hour : cHoursArray) {
tCrHours += hour;
}
tGPA = tCrPoints/tCrHours;
if (tGPA >= 2) {
status = ("Pass");
} else {
status = ("Fail");
}
tArea.setText("Total Credit Points : " + tCrPoints + "\n" +
"Total Credit Hours : " + tCrHours + "\n\n" +
"Grade Point Average (GPA) : " + tGPA + "\n" +
"Status : " + status);
}
if (event.getSource() == clearAllButton) {
tArea.setText("");
cHours.setText("");
grade.setSelectedIndex(0);
tCrHours = 0.00;
tCrPoints = 0.00;
}
}
}
}