0
\$\begingroup\$

I am currently working on a GPA Calculator side project over holiday break to become more familiar with Swing, but I find the number formatting is more complicated than in regular Java. At the moment I have a working prototype, but the number formatting on the overall GPA is way to long. I have tried to achieve this in many different ways, but cannot find a solution that works with the way I have my program set up.

Really though, any critique on my code would be much appreciated. I just finished my first semester of programming and the more I learn, the more interesting it becomes.

import java.awt.*;
import javax.swing.*;

public class GpaCalculator extends JPanel {

static private JPanel masterPanel = new JPanel();
static private JLabel finalResults = new JLabel("test");
static private Double totalGrade = 0.00;
static private Double totalHours = 0.00;
static private Double hours;
static private Double echo;

// 4 classes
GpaCalculator (String class1, String class2, String class3, String class4, double grade1, double grade2, double grade3, double grade4, 
        double hours1, double hours2, double hours3, double hours4) {

    JPanel panel = new JPanel(); 
    Dimension panelD = new Dimension(125, 100);
    panel.setPreferredSize(panelD);
    add(panel);
    JLabel label = new JLabel(class1 + "  " + grade1);
    JLabel label2 = new JLabel(class2 + "  " + grade2);
    JLabel label3 = new JLabel(class3 + "  " + grade3);
    JLabel label4 = new JLabel(class4 + "  " + grade4);
    double grade = (grade1 * hours1 + grade2 * hours2 + grade3 * hours3 + grade4 * hours4);
    hours =+ hours1 + hours2 + hours3 + hours4;
    echo = grade / hours;
    JLabel results = new JLabel();

    results.setText("average grade: " + echo);
    panel.add(label);
    panel.add(label2);
    panel.add(label3);
    panel.add(label4);
    panel.add(results);

    panel.setLayout(new GridLayout (5,2,5,0));
    panel.setBorder(BorderFactory.createRaisedBevelBorder());
    totalGrade += grade;
    totalHours += hours;
}
// 3 classes
GpaCalculator (String class1, String class2, String class3, double grade1, double grade2, double grade3, 
        double hours1, double hours2, double hours3) {
    JPanel panel = new JPanel(); 
    Dimension panelD = new Dimension(125, 100);
    panel.setPreferredSize(panelD);
    add(panel);
    JLabel label = new JLabel(class1 + "  " + grade1);
    JLabel label2 = new JLabel(class2 + "  " + grade2);
    JLabel label3 = new JLabel(class3 + "  " + grade3);
    double grade = (grade1 * hours1 + grade2 * hours2 + grade3 * hours3);
    hours =+ hours1 + hours2 + hours3;
    echo = grade / hours;
    JLabel results = new JLabel();

    results.setText("average grade: " + echo);
    panel.add(label);
    panel.add(label2);
    panel.add(label3);
    panel.add(results);

    panel.setLayout(new GridLayout (4,2,5,0));
    panel.setBorder(BorderFactory.createRaisedBevelBorder());
    totalGrade += grade;
    totalHours += hours;
}
// 2 classes
GpaCalculator (String class1, String class2, double grade1, double grade2, double hours1, double hours2) {

    JPanel panel = new JPanel(); 
    Dimension panelD = new Dimension(125, 100);
    panel.setPreferredSize(panelD);
    add(panel);
    JLabel label = new JLabel(class1 + "  " + grade1);
    JLabel label2 = new JLabel(class2 + "  " + grade2);
    double grade = (grade1 * hours1 + grade2 * hours2);
    hours =+ hours1 + hours2;
    echo = grade / hours;
    JLabel results = new JLabel();

    results.setText("average grade: " + echo);
    panel.add(label);
    panel.add(label2);
    panel.add(results);

    panel.setLayout(new GridLayout (3,2,5,0));
    panel.setBorder(BorderFactory.createRaisedBevelBorder());
    totalGrade += grade;
    totalHours += hours;
}

public static void main(String[] args) {
    JFrame frame = new JFrame("GPA Calculator");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    masterPanel.add(new GpaCalculator("computer class", "philosophy", 4, 4, 2, 3));
    masterPanel.add(new GpaCalculator("english 1101", "algebra" , "psychology", "human com", 4, 4, 4, 3, 3, 3, 3, 3));
    masterPanel.add(new GpaCalculator("engl 1102", "precal", "health", 4, 4, 4, 3, 3, 2));
    masterPanel.add(new GpaCalculator("western civ", "amer lit", "nutrition", "comp prog", 4, 4, 4, 4, 3, 3, 3, 4));

    totalGrade /= totalHours;
    finalResults.setText(totalGrade.toString());
    masterPanel.add(finalResults);

    frame.add(masterPanel);
    frame.pack();
    frame.setVisible(true);
}

}
\$\endgroup\$

2 Answers 2

4
\$\begingroup\$

Everything is currently in one class, even though many different "things" are going on:

  • GUI-related stuff, drawing, etc.
  • The actual math behind calculating GPA for a class
  • Your program start (main method)

It would make sense to break it up into a few different classes to effectively have each class do one and only one thing, instead of many (un-related) things.

So have one class for your GUI stuff, one class to calculate GPA, and another class to house your main method (though technically you could get away with shoving this into the GUI portion)

Essentially we will start out with creating a class that represents a school class and its properties: name, grade, and hours

public class SchoolClass 
{
     private String name; 
     private double grade, hours; 

     public SchoolClass(String name, double grade, double hours)
     {
          this.name = name; 
          this.grade = grade; 

          this.hours = hours; 
     }

     /* Add other methods (like getters and setters here) */
}

I didn't name it class, as Class happens to be a class in java.lang, so to avoid a name-clash, I chose SchoolClass

This really isn't a big deal as anyone reading should be able to tell you aren't referring to java.lang.Class).

Now your class

public class GpaCalculator extends JPanel

should probably be renamed to something like GpaFrame, essentially have a class that extends JFrame (this eliminates having both JFrame + JPanel classes)

public class GpaFrame extends JFrame

Now your constructor signatures will change from being something like this

GpaCalculator (String class1, String class2, String class3, 
    String class4, double grade1, double grade2, double grade3, double grade4, 
    double hours1, double hours2, double hours3, double hours4)

to something like

GpaFrame(SchoolClass[] classes)

or even

GpaFrame(SchoolClass... classes)

The reason why the class is now extending JFrame is so as to encapsulate all the GUI related stuff into one class. So all your logic pertaining to JPanel still exists, just it is now inside the custom JFrame class.

Now there should be a separate class to do the GPA calculations, and call that GpaCalc or something on those lines.

This class will take in the SchoolClass[] that was passed to GpaFrame and will perform all the necessary mathematical calculations.

So now there won't be

double grade = (grade1 * hours1 + grade2 * hours2 + grade3 * hours3 + grade4 * hours4);
hours =+ hours1 + hours2 + hours3 + hours4;
echo = grade / hours;

inside of your GUI code.

So now coming back to the main method. Since everything is neatly separated, the main is really simple and clean:

public static void main(String[] args)
{
     GpaFrame gpa = new GpaFrame(/* Pass the SchoolClasses here */);
     gpa.setVisible(true);
}
\$\endgroup\$
2
\$\begingroup\$
// 2 classes
GpaCalculator (String class1, String class2, double grade1, double grade2, double hours1, double hours2) {
//...
// 3 classes
GpaCalculator (String class1, String class2, String class3, double grade1, double grade2, double grade3, 
        double hours1, double hours2, double hours3) {
//...
// 4 classes
GpaCalculator (String class1, String class2, String class3, String class4, double grade1, double grade2, double grade3, double grade4, 
        double hours1, double hours2, double hours3, double hours4) {

Hey is it just me or is there some repetition in this??

so... for two classes you have 2 Strings, 2 Grades and 2 Hours ... for three you have 3 Strings, 3 Grades and 3 Hours ... there's a pattern that wants to be extracted..

For a single class you have name, grade and hours. Let's encapsulate this into a class (pun not intended, but relevant)

public class Class {
    public String name;
    public double grade;
    public double hours;
}

Now your GPA calculator drops all that nasty copy-pasta and gets a single constructor:

// however many classes you damn please! :D
public GpaCalculator (Class[] classes) {
    // mrmblgrml something something mrmbglbmlg
    for (Class oneClass : classes) {
        // use the loops, luke!
    }
    // finished! :D
}

Use loops to process repetitions of the same kind of data... please!

\$\endgroup\$
1
  • \$\begingroup\$ I will look into this. Is this builder notation? I think the method I used was overloading, which is inferior to builder notation from what I read on other posts. \$\endgroup\$ Commented Dec 29, 2015 at 20:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.