Build a Java Swing Grade Planner

Build a Java Swing app that calculates grades and predicts Finals scores.

Introduction

30 Second Summary

Semester grades can look settled until one remaining exam changes the whole outcome. Students need a clear answer before deciding what score to aim for.

In this project, you will build a Java Swing desktop grade planner for one subject. It calculates a weighted semester grade or predicts the Finals score needed to pass.

What You'll Build

A compact Windows form turns your scores into a current standing, a required Finals score, or a completed semester result.

By the end of this project, you'll have:

  • A desktop calculator that accepts Prelim and Midterm scores with an optional Finals score. It displays a completed weighted grade with a clear status.
  • A prediction mode that shows the Finals score needed to pass. It also explains whether passing is already secured or mathematically impossible.
  • A student-proof workflow that replaces invalid-input crashes with friendly dialogs. Its documentation records five reproducible tests plus a fundamentals quiz.
  • Secret Mission: Add an optional target-grade field while preserving 60 as the default.

Are there any prerequisites?

You need Eclipse IDE on Windows. No Java experience is required.

Before We Start

Start by locking in who your single-subject grade planner serves. Your sentence connects the calculator to the decision it supports before you begin building.

Prepare Eclipse and Prove Java Runs

You have defined the student who needs the planner. The next risk is whether your computer can compile the Java code behind it.

Eclipse IDE gives you the workspace for the project.

A JDK supplies the compiler. It also supplies the runtime that launches your program.

In this step, get ready to:
  • Configure Eclipse to use Eclipse Temurin JDK 25.0.4.1+1 as its default.
  • Create the Java project with its package structure and starter class.
  • Run the starter class as a Java application.
Verify or install the JDK

Eclipse lists Java runtimes under Installed JREs. A checked entry becomes the default for compiling and launching Java programs.

  • Press the Windows key to open Windows search.
  • Type Eclipse IDE into the search field.
  • Press Enter to open Eclipse.
  • Click Window in the Eclipse menu bar.
  • Select Preferences....
  • Expand Java in the preferences list.
  • Select Installed JREs to check which JDK Eclipse can use.

Choose the tab that matches the JDK entries you see.

✔️ I see the required version

The list includes Eclipse Temurin JDK 25.0.4.1+1. Eclipse already has access to the required Java tools.

  • Select the checkbox beside Eclipse Temurin JDK 25.0.4.1+1.
  • Click the dialog's apply control to record the new default.
  • Close the Preferences dialog.

The checked JDK is now Eclipse's default for new Java projects.

ⓧ I see an older JDK

The listed JDK cannot provide the exact release required by this project. Install Eclipse Temurin JDK 25.0.4.1+1 before creating the project.

The installer may ask for Windows permission. That prompt allows the JDK files to be added to your computer.

  • Press the Windows key to open Windows search.
  • Type Windows PowerShell into the search field.
  • Press Enter to open Windows PowerShell.
  • Install the required JDK by running this command:
winget install EclipseAdoptium.Temurin.25.JDK

What does this command do?

This command installs the required Eclipse Temurin JDK through Windows Package Manager. Eclipse can use that JDK to compile and launch the planner.

  • Restart Eclipse after the installation completes.
  • Return to the Installed JREs list from earlier.
  • Add the new JDK to the list if Eclipse does not detect it automatically.
  • Select the checkbox beside Eclipse Temurin JDK 25.0.4.1+1.
  • Close the Preferences dialog after applying the change.

You should now see the required JDK checked as the default.

JDK installation did not complete?

  • Keep Windows PowerShell open until the installation reports completion.
  • Restart Eclipse so it can detect the newly installed JDK.

If the installation still fails, ask for help diagnosing the JDK installation.

ⓧ I do not see a JDK

Eclipse needs a full JDK before it can compile the starter class. Install Eclipse Temurin JDK 25.0.4.1+1 now.

The installer may ask for Windows permission. That prompt allows the JDK files to be added to your computer.

  • Press the Windows key to open Windows search.
  • Type Windows PowerShell into the search field.
  • Press Enter to open Windows PowerShell.
  • Install the required JDK by running this command:
winget install EclipseAdoptium.Temurin.25.JDK

What does this command do?

This command installs the required Eclipse Temurin JDK through Windows Package Manager. The installation gives Eclipse the Java compiler and runtime.

  • Restart Eclipse after the installation completes.
  • Return to the Installed JREs list from earlier.
  • Add the new JDK to the list if Eclipse does not detect it automatically.
  • Select the checkbox beside Eclipse Temurin JDK 25.0.4.1+1.
  • Close the Preferences dialog after applying the change.

You should now see the required JDK checked as the default.

JDK still missing from Eclipse?

  • Restart Eclipse after confirming the JDK installation completed.
  • Use the add control in Installed JREs to locate the installed JDK.

If Eclipse still cannot find it, ask for help connecting the installed JDK to Eclipse.

Create the project structure

Java code uses a hierarchy that keeps related source files easy to find. You will create one project with one package and one starter class.

How does Java organize code?

A project contains the source files for one application.

A package groups related Java types under one name.

A class is a blueprint that holds data or behavior. GradeCalculatorApp starts as the class that launches your application.

  • Click File in the Eclipse menu bar.
  • Select New.
  • Select Project....
  • Choose Java Project in the project wizard.
  • Continue to the Java project details.
  • Enter UCSemesterGradePlanner as the project name.
  • Complete the wizard with the configured default JDK.

You should see UCSemesterGradePlanner in the Package Explorer. This confirms Eclipse created the Java project.

  • Expand UCSemesterGradePlanner in the Package Explorer.
  • Right-click the src source folder.
  • Select New.
  • Select Package.
  • Enter gradecalculator as the package name.
  • Complete the package wizard.

You should see gradecalculator beneath src in the Package Explorer.

  • Right-click the gradecalculator package.
  • Select New.
  • Choose the Java class option to open the New Java Class wizard.
  • Enter GradeCalculatorApp as the class name.
  • Select the option that creates the public static void main(String[] args) method stub.
  • Complete the class wizard.

Eclipse should open GradeCalculatorApp.java from src/gradecalculator. The file now contains the application entry point.

Run the starter program

The main method is where Java starts this application. One print statement gives you a visible test of the entire setup.

  • Select all generated content in GradeCalculatorApp.java.
  • Replace it with this complete starter class:
package gradecalculator;

public class GradeCalculatorApp {
    public static void main(String[] args) {
        System.out.println("Java setup ready");
    }
}

What does this code do?

  • The package gradecalculator declaration places the class in the package you created.
  • The GradeCalculatorApp class contains the starter program.
  • The main method gives Java a starting point.
  • The System.out.println("Java setup ready") statement prints a confirmation message in the Eclipse Console.
  • Save GradeCalculatorApp.java by pressing Cmd+S on macOS or Ctrl+S on Windows.

Before you launch the class, what message do you expect Eclipse to display if the JDK and project are configured correctly?

  • Right-click GradeCalculatorApp.java in the Package Explorer.
  • Select Run As.
  • Select Java Application.

You should see Java setup ready in the Eclipse Console. You should not see a red error marker beside GradeCalculatorApp.java.

Starter class does not run?

  • Confirm GradeCalculatorApp.java is inside src/gradecalculator.
  • Confirm Eclipse still shows the required JDK as the checked default in Installed JREs.
  • Compare every brace and capital letter with the reference code below.

If Eclipse shows an error marker, ask for help diagnosing the starter class.

That is the setup hurdle cleared. Eclipse can now compile and launch your Java application.

✔️ Awesome, I've got everything!

Your starter file is saved. The successful Console message proves your Java setup works.

ⓧ I'd like to double check the full code

package gradecalculator;

public class GradeCalculatorApp {
    public static void main(String[] args) {
        System.out.println("Java setup ready");
    }
}

What should match?

Your file should contain the same package declaration and class name. The main method should print the same Console message.

Your Java workspace is ready. Next up, you will turn this starter class into a visible desktop grade calculator.

Build the First Visible Calculator

Your Java setup is proven inside Eclipse IDE. The starter class can compile successfully.

The next milestone is a visible Java Swing form that turns three scores into a weighted result. A direct calculation gives you fast feedback from the desktop app.

In this step, get ready to:
  • Build a desktop form for Prelim, Midterm, and Finals scores.
  • Connect a Calculate button to the weighted formula.
  • Check the calculator with a complete score set plus an empty Finals field.
Build the Swing form

A JFrame provides the application window. A GridLayout arranges each label beside its text field.

  • Switch back to GradeCalculatorApp.java in the open gradecalculator package.
  • Replace the existing starter code with the code below:
package gradecalculator;

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

public class GradeCalculatorApp extends JFrame {
    private final JTextField prelimField = new JTextField(8);
    private final JTextField midtermField = new JTextField(8);
    private final JTextField finalsField = new JTextField(8);
    private final JLabel resultLabel = new JLabel("Result: waiting for scores");

    public GradeCalculatorApp() {
        super("UC Semester Grade Planner");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(new GridLayout(5, 2, 8, 8));
        add(new JLabel("Prelim score:"));
        add(prelimField);
        add(new JLabel("Midterm score:"));
        add(midtermField);
        add(new JLabel("Finals score:"));
        add(finalsField);
        pack();
        setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new GradeCalculatorApp());
    }
}

What Does This Code Do?

  • The imports make GridLayout plus the Swing components available to the class.
  • Extending JFrame gives the class the behavior of a desktop window.
  • The four fields keep the input components plus the output component available to every method.
  • The constructor sets the title before arranging the visible components.
  • The main(...) method asks Swing to create the window on its event dispatching thread.
  • Save GradeCalculatorApp.java.
  • Right-click GradeCalculatorApp.java in Package Explorer.
  • Select Run As.
  • Select Java Application.

You should see a window titled UC Semester Grade Planner. It contains separate fields for Prelim, Midterm, and Finals scores.

Does the Form Stay Hidden?

If Eclipse shows an error marker, confirm that the package line still says package gradecalculator;. Check that every opening brace has a matching closing brace.

Help me fix my Swing window.

Connect the button to the calculation

An event listener runs a method when the learner clicks a button. The method converts each String from a text field into a primitive double for decimal arithmetic.

  • Close the planner window with its title-bar close button.
  • Place the following method between the constructor and main(...) in GradeCalculatorApp.java.
    private void calculate() {
        double prelim = Double.parseDouble(prelimField.getText());
        double midterm = Double.parseDouble(midtermField.getText());
        double finals = Double.parseDouble(finalsField.getText());
        double semesterGrade = prelim * 0.30 + midterm * 0.30 + finals * 0.40;
        resultLabel.setText(String.format("Semester grade: %.2f", semesterGrade));
    }

How Does the Formula Work?

  • Each getText() call reads the score as text.
  • Each Double.parseDouble(...) call converts that text into a decimal number.
  • The formula multiplies Prelim by 0.30. It gives Midterm the same weight.
  • The formula multiplies Finals by 0.40.
  • String formatting displays the result with two decimal places.
  • Select the existing constructor from public GradeCalculatorApp() through its closing brace.
  • Replace the selected constructor with this version:
    public GradeCalculatorApp() {
        super("UC Semester Grade Planner");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(new GridLayout(5, 2, 8, 8));
        add(new JLabel("Prelim score:"));
        add(prelimField);
        add(new JLabel("Midterm score:"));
        add(midtermField);
        add(new JLabel("Finals score:"));
        add(finalsField);
        JButton calculateButton = new JButton("Calculate");
        calculateButton.addActionListener(event -> calculate());
        add(calculateButton);
        add(new JLabel(""));
        add(resultLabel);
        add(new JLabel(""));
        pack();
        setVisible(true);
    }

What Changed in the Form?

  • The constructor creates a button named calculateButton with the visible label Calculate.
  • The action listener calls calculate() after a click.
  • The form now includes resultLabel so the calculated grade has a visible destination.
  • Save GradeCalculatorApp.java.
  • Right-click GradeCalculatorApp.java in Package Explorer.
  • Select Run As.
  • Select Java Application.

You should see the new Calculate button. The result area starts with Result: waiting for scores.

Is the Calculate Button Missing?

Confirm that the constructor creates calculateButton. Check that the constructor adds it before calling pack().

Help me find the missing button.

✔️ Awesome, I've got everything!

Your form has three score fields, a Calculate button, and a result label. Make sure GradeCalculatorApp.java is saved.

ⓧ I'd like to double check the full code

package gradecalculator;

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

public class GradeCalculatorApp extends JFrame {
    private final JTextField prelimField = new JTextField(8);
    private final JTextField midtermField = new JTextField(8);
    private final JTextField finalsField = new JTextField(8);
    private final JLabel resultLabel = new JLabel("Result: waiting for scores");

    public GradeCalculatorApp() {
        super("UC Semester Grade Planner");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(new GridLayout(5, 2, 8, 8));
        add(new JLabel("Prelim score:"));
        add(prelimField);
        add(new JLabel("Midterm score:"));
        add(midtermField);
        add(new JLabel("Finals score:"));
        add(finalsField);
        JButton calculateButton = new JButton("Calculate");
        calculateButton.addActionListener(event -> calculate());
        add(calculateButton);
        add(new JLabel(""));
        add(resultLabel);
        add(new JLabel(""));
        pack();
        setVisible(true);
    }

    private void calculate() {
        double prelim = Double.parseDouble(prelimField.getText());
        double midterm = Double.parseDouble(midtermField.getText());
        double finals = Double.parseDouble(finalsField.getText());
        double semesterGrade = prelim * 0.30 + midterm * 0.30 + finals * 0.40;
        resultLabel.setText(String.format("Semester grade: %.2f", semesterGrade));
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new GradeCalculatorApp());
    }
}
Test the complete and missing score paths

A known score set confirms that the button reaches the formula. You can then test how the same calculation behaves when one score has no text.

  • Enter 70 in the Prelim score field.
  • Enter 80 in the Midterm score field.
  • Enter 50 in the Finals score field.

Before you click Calculate, consider whether the semester grade will land above or below 60.00.

  • Click Calculate.

You should see Semester grade: 65.00 in the form.

Your first desktop calculation is live. The form now turns three scores into a weighted result on demand.

  • Clear the Finals score field.

Before you click again, consider whether blank text can still become a decimal score.

  • Click Calculate.
  • Switch back to the Eclipse Console from earlier.

The result stops updating. You should see a stack trace containing NumberFormatException in the Console.

This Failure Is Intentional

The empty field returns an empty String. Double.parseDouble(...) cannot convert that value.

The exception proves that the direct three-score version needs a separate path for missing Finals input.

  • Close the planner window with its title-bar close button.

The visible calculator works when all three scores are present. Next, you'll separate the formula into a grade object that can answer the missing-Finals question.

Move Grade Rules into a Model

Your Swing form can calculate a completed semester grade. The empty Finals field exposed calculation rules that are tangled inside the button method.

This step moves those rules into a GradeCalculator object. The form can then choose between a completed-grade calculation and a prediction.

In this step, get ready to:
  • Create a model that owns the grading constants and score data.
  • Add methods for completed grades and Finals predictions.
  • Delegate the interface calculations to a GradeCalculator object.
Create the grade model

A model keeps related data and behavior in one class. Its private fields use encapsulation to protect each calculator object's score data.

Named constants give the configured weights a clear home. The constructor receives the two completed scores when a new calculator object is created.

  • In Eclipse, find the gradecalculator package in the Package Explorer.
  • Right-click the gradecalculator package.
  • Open the New Java Class wizard.
  • Enter GradeCalculator in the Name field.
  • Complete the wizard to create GradeCalculator.java inside src/gradecalculator.

You will see GradeCalculator.java open in the editor. That new file gives the grade rules their own class.

  • Replace the generated contents of GradeCalculator.java with this initial model code:
package gradecalculator;

/**
 * Holds the learner-confirmed grading rules and performs grade calculations.
 */
public class GradeCalculator {
    public static final double PRELIM_WEIGHT = 0.30;
    public static final double MIDTERM_WEIGHT = 0.30;
    public static final double FINALS_WEIGHT = 0.40;
    public static final double PASSING_GRADE = 60.0;

    private final double prelim;
    private final double midterm;

    public GradeCalculator(double prelim, double midterm) {
        this.prelim = prelim;
        this.midterm = midterm;
    }
}

What does this code do?

  • The four public static final double constants name the configured weights and passing grade.
  • The private prelim and midterm fields store each calculator object's completed scores.
  • The constructor uses this to assign each parameter to its matching field.
  • Save GradeCalculator.java.
  • Select GradeCalculatorApp.java in the Package Explorer.
  • Choose Run As.
  • Choose Java Application.
  • Enter 70 in the Prelim field.
  • Enter 80 in the Midterm field.
  • Enter 50 in the Finals field.
  • Click Calculate.

You will still see Semester grade: 65.00. The new model compiles without changing the existing calculator behavior.

Seeing an error marker in the model?

Check that the file is named GradeCalculator.java. Its public class name must match that filename exactly.

Confirm that the file begins with package gradecalculator;.

Ask for help with the model error.

Add focused calculation methods

Each model method answers one grade question. This keeps the weighted formula reusable across completed-grade and prediction modes.

  • Return to GradeCalculator.java.
  • Place your cursor before the final closing brace.
  • Add the weighted-score methods by pasting this code:
    public double calculateEarnedPointsBeforeFinals() {
        return prelim * PRELIM_WEIGHT + midterm * MIDTERM_WEIGHT;
    }

    public double calculateCurrentStanding() {
        double completedWeight = PRELIM_WEIGHT + MIDTERM_WEIGHT;
        return calculateEarnedPointsBeforeFinals() / completedWeight;
    }

    public double calculateRequiredFinal() {
        return (PASSING_GRADE - calculateEarnedPointsBeforeFinals()) / FINALS_WEIGHT;
    }

    public double calculateSemesterGrade(double finals) {
        return calculateEarnedPointsBeforeFinals() + finals * FINALS_WEIGHT;
    }

How do these calculations differ?

  • calculateEarnedPointsBeforeFinals() returns the weighted points already earned.
  • calculateCurrentStanding() normalizes the two completed periods across their combined weight.
  • calculateRequiredFinal() solves for the Finals score needed to reach PASSING_GRADE.
  • calculateSemesterGrade(double finals) adds the weighted Finals contribution to the points already earned.
  • Save GradeCalculator.java.
  • Confirm that no red error marker appears beside the new methods.

Eclipse can now compile every grade calculation inside the model. The interface still needs a decision method for each possible result.

Do the methods appear outside the class?

Move the new methods above the final closing brace in GradeCalculator.java. Every method must sit inside the GradeCalculator class.

Ask for help placing the methods.

  • Place your cursor after calculateSemesterGrade(double finals).
  • Add the status and prediction methods by pasting this code:
    public boolean isPassing(double semesterGrade) {
        return semesterGrade >= PASSING_GRADE;
    }

    public String getPredictionMessage() {
        double requiredFinal = calculateRequiredFinal();

        if (requiredFinal <= 0.0) {
            return "Passing is already secured before Finals.";
        }

        if (requiredFinal > 100.0) {
            return String.format(
                    "Passing is not possible with the remaining Finals period. Required: %.2f",
                    requiredFinal);
        }

        return String.format("Required Finals score to pass: %.2f", requiredFinal);
    }

How does the model choose an outcome?

  • isPassing(double semesterGrade) compares a completed grade with the configured passing grade.
  • getPredictionMessage() calculates the required Finals score before choosing a message.
  • A required score at or below 0.0 means passing is already secured.
  • A required score above 100.0 means passing is mathematically impossible with Finals alone.
  • Save GradeCalculator.java.
  • Confirm that the model has no red error markers.

Seeing errors around the prediction method?

Check that getPredictionMessage() appears after isPassing(double semesterGrade) and before the class's final closing brace.

Ask for help with the prediction method.

✔️ Awesome, I've got everything!

Great. Double-check that you saved GradeCalculator.java.

ⓧ I'd like to double check the full code

package gradecalculator;

/**
 * Holds the learner-confirmed grading rules and performs grade calculations.
 */
public class GradeCalculator {
    public static final double PRELIM_WEIGHT = 0.30;
    public static final double MIDTERM_WEIGHT = 0.30;
    public static final double FINALS_WEIGHT = 0.40;
    public static final double PASSING_GRADE = 60.0;

    private final double prelim;
    private final double midterm;

    public GradeCalculator(double prelim, double midterm) {
        this.prelim = prelim;
        this.midterm = midterm;
    }

    public double calculateEarnedPointsBeforeFinals() {
        return prelim * PRELIM_WEIGHT + midterm * MIDTERM_WEIGHT;
    }

    public double calculateCurrentStanding() {
        double completedWeight = PRELIM_WEIGHT + MIDTERM_WEIGHT;
        return calculateEarnedPointsBeforeFinals() / completedWeight;
    }

    public double calculateRequiredFinal() {
        return (PASSING_GRADE - calculateEarnedPointsBeforeFinals()) / FINALS_WEIGHT;
    }

    public double calculateSemesterGrade(double finals) {
        return calculateEarnedPointsBeforeFinals() + finals * FINALS_WEIGHT;
    }

    public boolean isPassing(double semesterGrade) {
        return semesterGrade >= PASSING_GRADE;
    }

    public String getPredictionMessage() {
        double requiredFinal = calculateRequiredFinal();

        if (requiredFinal <= 0.0) {
            return "Passing is already secured before Finals.";
        }

        if (requiredFinal > 100.0) {
            return String.format(
                    "Passing is not possible with the remaining Finals period. Required: %.2f",
                    requiredFinal);
        }

        return String.format("Required Finals score to pass: %.2f", requiredFinal);
    }
}
Delegate calculations to the model

The interface should collect input and display output. A GradeCalculator object now performs the grade math between those two jobs.

  • Switch back to GradeCalculatorApp.java.
  • Find this class header and field block:
public class GradeCalculatorApp extends JFrame {
    private final JTextField prelimField = new JTextField(8);
    private final JTextField midtermField = new JTextField(8);
    private final JTextField finalsField = new JTextField(8);
    private final JLabel resultLabel = new JLabel("Result: waiting for scores");

What needs to change here?

The current field block has one output label. The updated interface needs a separate label for current standing.

  • Replace that class header and field block with this updated version:
/**
 * Collects student input and displays results from GradeCalculator.
 */
public class GradeCalculatorApp extends JFrame {
    private final JTextField prelimField = new JTextField(8);
    private final JTextField midtermField = new JTextField(8);
    private final JTextField finalsField = new JTextField(8);
    private final JLabel currentLabel = new JLabel("Current standing: waiting for scores");
    private final JLabel resultLabel = new JLabel("Result: waiting for scores");

What changed?

  • The class documentation records the interface's responsibility.
  • currentLabel gives current standing and earned weighted points their own output area.
  • Save GradeCalculatorApp.java.
  • Confirm that no red error marker appears beside currentLabel.

The constructor still builds the earlier five-row form. Update that complete constructor so the new output label has a place in the window.

  • Find the existing GradeCalculatorApp() constructor.
  • Replace the constructor with this updated form layout:
    public GradeCalculatorApp() {
        super("UC Semester Grade Planner");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(new GridLayout(6, 2, 8, 8));

        add(new JLabel("Prelim score (0-100):"));
        add(prelimField);
        add(new JLabel("Midterm score (0-100):"));
        add(midtermField);
        add(new JLabel("Finals score (optional):"));
        add(finalsField);

        JButton calculateButton = new JButton("Calculate / Predict");
        calculateButton.addActionListener(event -> calculate());
        add(calculateButton);
        add(new JLabel("Leave Finals blank to predict"));

        add(currentLabel);
        add(new JLabel(""));
        add(resultLabel);
        add(new JLabel(""));

        pack();
        setVisible(true);
    }

What does the updated constructor do?

  • The six-row GridLayout makes room for separate current-standing and result labels.
  • The field labels now describe the accepted score range and the optional Finals value.
  • The button and helper label tell the student that one action supports calculation and prediction.
  • Save GradeCalculatorApp.java.
  • Close the calculator window from the earlier check.
  • Select GradeCalculatorApp.java in the Package Explorer.
  • Choose Run As.
  • Choose Java Application.

You will see the renamed score fields and the new Calculate / Predict button. You will also see separate waiting messages for current standing and the result.

Does the form still show five rows?

Check that the constructor uses new GridLayout(6, 2, 8, 8). Confirm that currentLabel is added before resultLabel.

Ask for help with the form layout.

The final change replaces the inline arithmetic with model method calls. It also checks whether the Finals field is empty before parsing it.

  • Close the updated calculator window.
  • Find the existing calculate() method in GradeCalculatorApp.java.
  • Replace the complete method with this delegated calculation flow:
    private void calculate() {
        double prelim = Double.parseDouble(prelimField.getText());
        double midterm = Double.parseDouble(midtermField.getText());
        GradeCalculator calculator = new GradeCalculator(prelim, midterm);
        currentLabel.setText(String.format(
                "Current standing: %.2f | Earned weighted points: %.2f",
                calculator.calculateCurrentStanding(),
                calculator.calculateEarnedPointsBeforeFinals()));

        String finalsText = finalsField.getText().trim();
        if (finalsText.isEmpty()) {
            resultLabel.setText(calculator.getPredictionMessage());
        } else {
            double finals = Double.parseDouble(finalsText);
            double semesterGrade = calculator.calculateSemesterGrade(finals);
            String status = calculator.isPassing(semesterGrade)
                    ? "PASS"
                    : "NOT YET PASSING";
            resultLabel.setText(String.format(
                    "Semester grade: %.2f | Status: %s",
                    semesterGrade,
                    status));
        }
    }

How does delegation work?

  • The method creates one GradeCalculator object from the Prelim and Midterm values.
  • An empty finalsText selects the prediction path before any Finals parsing happens.
  • A supplied Finals value selects the completed-grade path.
  • The interface formats the model's returned values for the student.
  • Save GradeCalculatorApp.java.
  • Select GradeCalculatorApp.java in the Package Explorer.
  • Choose Run As.
  • Choose Java Application.
  • Enter 70 in the Prelim field.
  • Enter 80 in the Midterm field.
  • Enter 50 in the Finals field.
  • Click Calculate / Predict.

You will see Semester grade: 65.00 | Status: PASS. The completed-grade path now uses the model.

  • Replace the Prelim value with 70.
  • Replace the Midterm value with 70.
  • Clear the Finals field.

Before you click Calculate / Predict, what should the model report when Finals is blank?

  • Click Calculate / Predict.

You will see Current standing: 70.00 | Earned weighted points: 42.00 and Required Finals score to pass: 45.00. The blank Finals field now activates prediction without a NumberFormatException.

That is the original limitation solved. Your interface now turns missing Finals data into a useful decision for the student.

Does blank Finals still stop the result?

Check that finalsField.getText().trim() runs before the empty-field condition. Confirm that Finals parsing appears only inside the else branch.

Check that both Java files begin with the same gradecalculator package declaration.

Ask for help with the delegation flow.

✔️ Awesome, I've got everything!

Great. Double-check that you saved GradeCalculatorApp.java.

ⓧ I'd like to double check the full code

package gradecalculator;

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

/**
 * Collects student input and displays results from GradeCalculator.
 */
public class GradeCalculatorApp extends JFrame {
    private final JTextField prelimField = new JTextField(8);
    private final JTextField midtermField = new JTextField(8);
    private final JTextField finalsField = new JTextField(8);
    private final JLabel currentLabel = new JLabel("Current standing: waiting for scores");
    private final JLabel resultLabel = new JLabel("Result: waiting for scores");

    public GradeCalculatorApp() {
        super("UC Semester Grade Planner");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(new GridLayout(6, 2, 8, 8));

        add(new JLabel("Prelim score (0-100):"));
        add(prelimField);
        add(new JLabel("Midterm score (0-100):"));
        add(midtermField);
        add(new JLabel("Finals score (optional):"));
        add(finalsField);

        JButton calculateButton = new JButton("Calculate / Predict");
        calculateButton.addActionListener(event -> calculate());
        add(calculateButton);
        add(new JLabel("Leave Finals blank to predict"));

        add(currentLabel);
        add(new JLabel(""));
        add(resultLabel);
        add(new JLabel(""));

        pack();
        setVisible(true);
    }

    private void calculate() {
        double prelim = Double.parseDouble(prelimField.getText());
        double midterm = Double.parseDouble(midtermField.getText());
        GradeCalculator calculator = new GradeCalculator(prelim, midterm);
        currentLabel.setText(String.format(
                "Current standing: %.2f | Earned weighted points: %.2f",
                calculator.calculateCurrentStanding(),
                calculator.calculateEarnedPointsBeforeFinals()));

        String finalsText = finalsField.getText().trim();
        if (finalsText.isEmpty()) {
            resultLabel.setText(calculator.getPredictionMessage());
        } else {
            double finals = Double.parseDouble(finalsText);
            double semesterGrade = calculator.calculateSemesterGrade(finals);
            String status = calculator.isPassing(semesterGrade)
                    ? "PASS"
                    : "NOT YET PASSING";
            resultLabel.setText(String.format(
                    "Semester grade: %.2f | Status: %s",
                    semesterGrade,
                    status));
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new GradeCalculatorApp());
    }
}

Your grade rules now live in a reusable model. Next, you will protect that model from invalid student input.

Validate Scores and Display Outcomes

Your Java Swing planner already calculates completed grades. It also predicts the Finals score a student needs.

The current input path still trusts every value typed into the form. Text such as abc can stop a calculation.

Values such as NaN, -1, or 101 can produce unsafe results.

This step adds input validation at the interface boundary. Every unsafe score will lead to a friendly dialog.

In this step, get ready to:
  • Centralize parsing in a range-aware helper method.
  • Convert unsafe values into friendly validation dialogs.
  • Verify the full outcome matrix.
Centralize score validation

A validation helper protects the grade engine before it receives a score. The same method can enforce one set of rules for every text field.

When a value breaks those rules, the helper throws an exception with a specific message. The interface will use that message in the next substep.

  • In the Package Explorer, double-click GradeCalculatorApp.java.
  • Find the main method near the bottom of the class.
  • Insert the validation helper immediately above main by pasting this code:
    private double readScore(JTextField field, String name) {
        String text = field.getText().trim();
        if (text.isEmpty()) {
            throw new IllegalArgumentException(name + " is required.");
        }

        double value;
        try {
            value = Double.parseDouble(text);
        } catch (NumberFormatException exception) {
            throw new IllegalArgumentException(name + " must be a number.");
        }

        if (!Double.isFinite(value) || value < 0.0 || value > 100.0) {
            throw new IllegalArgumentException(name + " must be from 0 to 100.");
        }

        return value;
    }

What does this helper do?

  • The trim() call removes surrounding whitespace before validation begins.
  • The isEmpty() check rejects a required score with no text.
  • The Double.parseDouble(...) call converts numeric text into a double value.
  • The NumberFormatException handler turns nonnumeric text into a student-friendly message.
  • The Double.isFinite(...) check rejects NaN or an infinite value.
  • The comparisons reject values below 0.0 or above 100.0.
  • Save GradeCalculatorApp.java by pressing Cmd+S on macOS or Ctrl+S on Windows.
  • Confirm Eclipse shows no red error marker beside the readScore method.

Seeing an error marker?

  • Check that readScore sits after the closing brace for calculate().
  • Compare every opening brace with its matching closing brace.

Help me debug the placement of my Java validation method.

Catch input errors at the interface

A try block contains work that can fail. A matching catch block converts a known failure into an interface response.

  • Find the calculate() method in GradeCalculatorApp.java.
  • Replace the entire method with this guarded version:
    private void calculate() {
        try {
            double prelim = readScore(prelimField, "Prelim");
            double midterm = readScore(midtermField, "Midterm");
            GradeCalculator calculator = new GradeCalculator(prelim, midterm);

            currentLabel.setText(String.format(
                    "Current standing: %.2f | Earned weighted points: %.2f",
                    calculator.calculateCurrentStanding(),
                    calculator.calculateEarnedPointsBeforeFinals()));

            String finalsText = finalsField.getText().trim();
            if (finalsText.isEmpty()) {
                resultLabel.setText(calculator.getPredictionMessage());
            } else {
                double finals = readScore(finalsField, "Finals");
                double semesterGrade = calculator.calculateSemesterGrade(finals);
                String status = calculator.isPassing(semesterGrade)
                        ? "PASS"
                        : "NOT YET PASSING";
                resultLabel.setText(String.format(
                        "Semester grade: %.2f | Status: %s",
                        semesterGrade,
                        status));
            }
        } catch (IllegalArgumentException exception) {
            resultLabel.setText("Fix the input and try again.");
            JOptionPane.showMessageDialog(this, exception.getMessage());
        }
    }

What does this change do?

  • The calls to readScore apply the same validation rules to Prelim, Midterm, and Finals.
  • The try block contains every operation that depends on safe scores.
  • The catch block handles each IllegalArgumentException from the validation helper.
  • The result label changes to Fix the input and try again. after a validation failure.
  • The JOptionPane.showMessageDialog(...) call displays the helper's specific message.
  • Save GradeCalculatorApp.java.
  • Right-click GradeCalculatorApp.java in the Package Explorer.
  • Select Run As from the context menu.
  • Select Java Application.
  • Enter abc in the Prelim field.
  • Enter 70 in the Midterm field.
  • Clear the Finals field.

Before you click, predict whether the app will calculate a grade or reject the text.

  • Click Calculate / Predict.

You will see Prelim must be a number. in a dialog. The result label reads Fix the input and try again..

You have contained the riskiest input path. Unsafe text now returns a useful message while the app stays open.

Nonnumeric input is one unsafe case. The helper also protects the grade engine from non-finite values and scores outside the allowed range.

  • Dismiss the current validation dialog.
  • Replace the Prelim value with NaN.
  • Click Calculate / Predict.

You will see Prelim must be from 0 to 100. in the dialog.

  • Dismiss the validation dialog.
  • Replace the Prelim value with -1.
  • Click Calculate / Predict.

You will see the same range message because -1 is below the minimum score.

  • Dismiss the validation dialog.
  • Replace the Prelim value with 101.
  • Click Calculate / Predict.

You will see the same range message because 101 is above the maximum score.

Missing the validation dialog?

  • Confirm every score is read through readScore inside calculate().
  • Confirm the catch block surrounds the entire calculation path.
  • Relaunch the saved class as a Java application.

Help me find why my Java validation dialog is not appearing.

✔️ Awesome, I've got everything!

Your saved GradeCalculatorApp.java now contains the complete validation path.

ⓧ I'd like to double check the full code

package gradecalculator;

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

/**
 * Collects student input and displays results from GradeCalculator.
 */
public class GradeCalculatorApp extends JFrame {
    private final JTextField prelimField = new JTextField(8);
    private final JTextField midtermField = new JTextField(8);
    private final JTextField finalsField = new JTextField(8);
    private final JLabel currentLabel = new JLabel("Current standing: waiting for scores");
    private final JLabel resultLabel = new JLabel("Result: waiting for scores");

    public GradeCalculatorApp() {
        super("UC Semester Grade Planner");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(new GridLayout(6, 2, 8, 8));

        add(new JLabel("Prelim score (0-100):"));
        add(prelimField);
        add(new JLabel("Midterm score (0-100):"));
        add(midtermField);
        add(new JLabel("Finals score (optional):"));
        add(finalsField);

        JButton calculateButton = new JButton("Calculate / Predict");
        calculateButton.addActionListener(event -> calculate());
        add(calculateButton);
        add(new JLabel("Leave Finals blank to predict"));

        add(currentLabel);
        add(new JLabel(""));
        add(resultLabel);
        add(new JLabel(""));

        pack();
        setVisible(true);
    }

    private void calculate() {
        try {
            double prelim = readScore(prelimField, "Prelim");
            double midterm = readScore(midtermField, "Midterm");
            GradeCalculator calculator = new GradeCalculator(prelim, midterm);

            currentLabel.setText(String.format(
                    "Current standing: %.2f | Earned weighted points: %.2f",
                    calculator.calculateCurrentStanding(),
                    calculator.calculateEarnedPointsBeforeFinals()));

            String finalsText = finalsField.getText().trim();
            if (finalsText.isEmpty()) {
                resultLabel.setText(calculator.getPredictionMessage());
            } else {
                double finals = readScore(finalsField, "Finals");
                double semesterGrade = calculator.calculateSemesterGrade(finals);
                String status = calculator.isPassing(semesterGrade)
                        ? "PASS"
                        : "NOT YET PASSING";
                resultLabel.setText(String.format(
                        "Semester grade: %.2f | Status: %s",
                        semesterGrade,
                        status));
            }
        } catch (IllegalArgumentException exception) {
            resultLabel.setText("Fix the input and try again.");
            JOptionPane.showMessageDialog(this, exception.getMessage());
        }
    }

    private double readScore(JTextField field, String name) {
        String text = field.getText().trim();
        if (text.isEmpty()) {
            throw new IllegalArgumentException(name + " is required.");
        }

        double value;
        try {
            value = Double.parseDouble(text);
        } catch (NumberFormatException exception) {
            throw new IllegalArgumentException(name + " must be a number.");
        }

        if (!Double.isFinite(value) || value < 0.0 || value > 100.0) {
            throw new IllegalArgumentException(name + " must be from 0 to 100.");
        }

        return value;
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new GradeCalculatorApp());
    }
}

What should match?

Use this file as a comparison reference. Your calculate() method should call readScore and catch IllegalArgumentException.

Verify every outcome

The validation boundary is working. The remaining checks prove that every grade decision reaches the correct branch.

  • Dismiss the current validation dialog.
  • Enter 70 in the Prelim field.
  • Confirm the Midterm field contains 70.
  • Confirm the Finals field is blank.

Before you click, predict which prediction message two scores of 70 will produce.

  • Click Calculate / Predict.

You will see a current standing of 70.00 and a required Finals score of 45.00.

  • Replace the Prelim value with 20.
  • Replace the Midterm value with 20.

Before you click, predict whether a Finals score from 0 to 100 can still reach the passing grade.

  • Click Calculate / Predict.

You will see that passing is not possible. The required Finals score is 120.00.

  • Replace the Prelim value with 100.
  • Replace the Midterm value with 100.

Before you click, predict whether the student still needs any points from Finals.

  • Click Calculate / Predict.

You will see Passing is already secured before Finals..

  • Replace the Prelim value with 70.
  • Replace the Midterm value with 80.
  • Enter 50 in the Finals field.

Before you click, predict whether the completed semester grade will pass.

  • Click Calculate / Predict.

You will see Semester grade: 65.00 | Status: PASS.

  • Replace the Prelim value with 50.
  • Replace the Midterm value with 50.

Before the final click, predict whether a semester grade of 50.00 meets the configured threshold.

  • Click Calculate / Predict.

You will see Semester grade: 50.00 | Status: NOT YET PASSING.

That is the calculator student-proofed. Every completed-grade outcome and prediction branch now has a visible result.

Your grade planner now handles unsafe input without losing its calculation flow. Next up, you will document the formula and verify the app with a repeatable test table.

Document, Test, and Check Fundamentals

Your Java Swing grade planner now handles valid scores plus unsafe input. It also covers every required prediction outcome.

A working program becomes a complete project when another person can run it. Clear documentation plus repeatable tests provide that proof.

In this step, get ready to:
  • Create a complete README.md for the grade planner.
  • Reproduce the five documented test cases.
  • Complete the fundamentals quiz before reviewing its answer key.
Create the project README

A README uses Markdown to record a project's purpose plus its operating assumptions. It gives another learner one place to find the design and run instructions.

  • In Eclipse from earlier, select UCSemesterGradePlanner in the Package Explorer.
  • Right-click the selected project.
  • Select New.
  • Select File.
  • Enter README.md in the File name field.
  • Click Finish.

You will see README.md open in the editor. Its position directly beneath UCSemesterGradePlanner confirms that it sits at the project root.

  • Add the project purpose and design by pasting this content into README.md:
# UC Semester Grade Planner

A beginner Java Swing project that calculates a semester grade or predicts the Finals score needed to reach the configured passing grade.

## Policy note

The formula in this project is a learner-confirmed project requirement. It is not presented as a publicly verified university-wide policy.

- Prelim: 30%
- Midterm: 30%
- Finals: 40%
- Default passing grade: 60

## Requirements

- Windows
- Eclipse IDE
- Eclipse Temurin JDK 25.0.4.1+1

## Design

- `GradeCalculator` stores the grading constants and performs every grade calculation.
- `GradeCalculatorApp` collects input, responds to the button click, validates scores, and displays results.

This separation keeps the grading rules independent from the Swing interface.

What does this section document?

  • The policy note identifies the percentages as configured project rules.
  • The requirements record the environment used to run the application.
  • The GradeCalculator class owns the grading rules.
  • The GradeCalculatorApp class owns input plus interface behavior.
  • Save README.md.
  • Confirm that the editor shows the Policy note heading.
  • Confirm that the editor shows the Design heading.

README in the wrong location?

Check that README.md appears directly beneath UCSemesterGradePlanner in the Package Explorer.

Use Help me confirm whether README.md is at the root of my Eclipse Java project..

  • Add the run instructions plus the test table by pasting this content at the end of README.md:


## Run the app

1. Open `GradeCalculatorApp.java` in Eclipse.
2. Select `Run As > Java Application`.
3. Enter Prelim and Midterm scores.
4. Leave Finals blank to predict the required score, or enter Finals to calculate the completed semester grade.

## Test table

| Case | Prelim | Midterm | Finals | Expected observation |
| --- | ---: | ---: | ---: | --- |
| Achievable prediction | 70 | 70 | blank | Current standing 70.00; required Finals 45.00 |
| Impossible prediction | 20 | 20 | blank | Required Finals 120.00; passing is not possible |
| Already secured | 100 | 100 | blank | Passing is already secured |
| Completed pass | 70 | 80 | 50 | Semester grade 65.00; PASS |
| Invalid text | abc | 70 | blank | Friendly message: Prelim must be a number |

What does the test table prove?

Each row pairs controlled inputs with one expected observation. Together the rows cover completed grades plus every required prediction outcome.

The invalid-text row checks that unsafe input reaches the friendly validation boundary.

  • Save README.md.
  • Confirm that the Run the app section contains four numbered instructions.
  • Confirm that the Test table section contains five case rows.

Test table looks malformed?

Compare the vertical pipe characters in each row with the code block above. A missing pipe character can move text into the wrong column.

Use Help me find the malformed row in my README test table..

  • Add the quiz questions by pasting this content at the end of README.md:


## Fundamentals quiz

Answer these before reading the key.

1. Why are scores stored as `double` values after they are read from `JTextField` objects?
2. What do `static` and `final` communicate about a grading constant?
3. What job does the `GradeCalculator` constructor perform?
4. Why does `getPredictionMessage()` use conditional statements?
5. Why is `readScore(...)` in the GUI while the weighted formula is in `GradeCalculator`?

What does the quiz check?

  • The first question checks the difference between text and decimal data.
  • The second question checks how grading constants behave.
  • The third question checks the purpose of a constructor.
  • The final two questions check conditional logic plus class responsibilities.
  • Save README.md.
  • Confirm that the Fundamentals quiz section contains five numbered questions.

Quiz question missing?

Check that the numbered list runs from 1 through 5.

Use Help me compare my README quiz with the required five questions..

Execute the five test cases

A test case uses controlled inputs to check one expected behavior. Reproducing every row shows that the documentation matches the running application.

  • Switch back to GradeCalculatorApp.java from earlier.
  • Right-click GradeCalculatorApp.java in the Package Explorer.
  • Select Run As.
  • Select Java Application.

You will see the grade planner window with its three score fields. Keep this window open while you work through the table.

How to check each row

  • Use the values listed in the matching row of README.md.
  • Leave the Finals field empty when the row lists blank.
  • Click Calculate / Predict after entering the row's values.
  • Compare the displayed result with the row's expected observation.

Before you start the table, predict whether all five documented rows match the current app.

  • Run the Completed pass case from the test table.
  • Run the Achievable prediction case from the test table.
  • Run the Impossible prediction case from the test table.
  • Run the Already secured case from the test table.
  • Run the Invalid text case from the test table.

What should I see?

  • Completed pass shows Semester grade: 65.00 | Status: PASS.
  • Achievable prediction shows Current standing: 70.00.
  • Achievable prediction also shows Required Finals score to pass: 45.00.
  • Impossible prediction shows Passing is not possible with the remaining Finals period. Required: 120.00.
  • Already secured shows Passing is already secured before Finals..
  • Invalid text shows Prelim must be a number. in a dialog.
  • Record one check mark on paper for each matching test row.

That is the test pass complete. You now have evidence for completed grades, predictions, boundary outcomes, and unsafe input.

Did a test result differ?

Check that each field matches the row before clicking the button. Clear Finals completely for every prediction case.

Use Help me compare my grade planner result with the expected README test result..

Take the fundamentals quiz

The quiz checks whether you can explain the choices behind the running code. Your first attempt identifies any concept that needs a closer look.

  • Return to the README.md tab from earlier.
  • Scroll to the Fundamentals quiz heading.
  • Write your answers to all five questions on paper.

Before you reveal the key, predict whether your first score reaches 4 out of 5.

  • Reveal the answer key by pasting this content at the end of README.md:


## Answer key

1. A text field returns a `String`, while `double` supports decimal arithmetic needed for weighted grades.
2. `static` gives the class one shared value, and `final` prevents reassignment after initialization.
3. It initializes a new object's Prelim and Midterm state from constructor arguments.
4. Different numeric ranges require different outcomes: secured, impossible, or achievable.
5. Parsing belongs at the input boundary, while reusable grading rules belong in the model class.

Why keep an answer key?

The key connects each question to a specific choice in your code. A missed answer becomes a focused review topic.

  • Save README.md.
  • Confirm that the Answer key section contains five numbered explanations.

Answer key incomplete?

Count the numbered explanations beneath the Answer key heading. Copy any missing line from the code block again.

Use Help me identify the missing item in my README answer key..

  • Compare each paper answer with its matching explanation.
  • Award one point for every answer that communicates the same core idea.
  • Calculate your score out of 5.
  • Rewrite every missed answer in your own words.
  • Answer each missed question again without looking at the key.
  • Repeat the check until your score reaches at least 4 out of 5.

You have completed the knowledge check. Your score now reflects the data types, constants, constructor, conditionals, and class responsibilities behind the app.

✔️ Awesome, I've got everything!

Great work. Double-check that README.md is saved at the project root.

ⓧ I'd like to double check the full code

# UC Semester Grade Planner

A beginner Java Swing project that calculates a semester grade or predicts the Finals score needed to reach the configured passing grade.

## Policy note

The formula in this project is a learner-confirmed project requirement. It is not presented as a publicly verified university-wide policy.

- Prelim: 30%
- Midterm: 30%
- Finals: 40%
- Default passing grade: 60

## Requirements

- Windows
- Eclipse IDE
- Eclipse Temurin JDK 25.0.4.1+1

## Design

- `GradeCalculator` stores the grading constants and performs every grade calculation.
- `GradeCalculatorApp` collects input, responds to the button click, validates scores, and displays results.

This separation keeps the grading rules independent from the Swing interface.

## Run the app

1. Open `GradeCalculatorApp.java` in Eclipse.
2. Select `Run As > Java Application`.
3. Enter Prelim and Midterm scores.
4. Leave Finals blank to predict the required score, or enter Finals to calculate the completed semester grade.

## Test table

| Case | Prelim | Midterm | Finals | Expected observation |
| --- | ---: | ---: | ---: | --- |
| Achievable prediction | 70 | 70 | blank | Current standing 70.00; required Finals 45.00 |
| Impossible prediction | 20 | 20 | blank | Required Finals 120.00; passing is not possible |
| Already secured | 100 | 100 | blank | Passing is already secured |
| Completed pass | 70 | 80 | 50 | Semester grade 65.00; PASS |
| Invalid text | abc | 70 | blank | Friendly message: Prelim must be a number |

## Fundamentals quiz

Answer these before reading the key.

1. Why are scores stored as `double` values after they are read from `JTextField` objects?
2. What do `static` and `final` communicate about a grading constant?
3. What job does the `GradeCalculator` constructor perform?
4. Why does `getPredictionMessage()` use conditional statements?
5. Why is `readScore(...)` in the GUI while the weighted formula is in `GradeCalculator`?

## Answer key

1. A text field returns a `String`, while `double` supports decimal arithmetic needed for weighted grades.
2. `static` gives the class one shared value, and `final` prevents reassignment after initialization.
3. It initializes a new object's Prelim and Midterm state from constructor arguments.
4. Different numeric ranges require different outcomes: secured, impossible, or achievable.
5. Parsing belongs at the input boundary, while reusable grading rules belong in the model class.

That is the full project path complete. Your grade planner now has runnable code, reproducible tests, clear documentation, and a checked explanation of its design.

Secret mission

Let the Student Choose a Target Grade

Your planner currently measures every result against a fixed passing grade of 60. Extend it with a target field so students can explore their own goals while keeping 60 as the default.

Clean Up Your Resources

Clean Up Your Resources

Your calculator runs locally through Java Swing in Eclipse with no ongoing service charges. Choose to keep the project available, pause the app, or remove the project entirely.

Resources you used:

  • The UCSemesterGradePlanner Eclipse project with its source files.
  • The project documentation in README.md.
  • The running UC Semester Grade Planner desktop app.

Keep everything running

No action needed. Choose this if you are still testing the custom target flow or refining the calculator.

  • Keep UCSemesterGradePlanner in Eclipse with its source files intact.
  • Keep README.md with the project as your run guide and test record.
  • Leave the desktop app open only while you are actively testing it.
  • Use the documented test cases in README.md whenever you change the grade rules.

Pause - I'll come back to this later

Stop the running tools to free their local memory. Your Eclipse project stays available for your next session.

  • Close the UC Semester Grade Planner window.
  • Close Eclipse.
  • Keep UCSemesterGradePlanner on your computer.
  • Confirm the calculator window is no longer visible.
  • Confirm Eclipse is no longer running.

Delete - I don't want to use this again

Remove the local project to start fresh. Deletion is permanent, so choose this only when you no longer need the source code or documentation.

  • Close the UC Semester Grade Planner window.
  • Select UCSemesterGradePlanner in the Package Explorer panel in Eclipse.
  • Right-click the selected project.
  • Choose the option that deletes the selected project.
  • Enable the setting that also removes the project contents from disk.
  • Confirm the deletion.
  • Check the Package Explorer panel after Eclipse finishes.

You should no longer see UCSemesterGradePlanner in Eclipse. Its source files and README.md are also removed from your computer.

Nice Work!

Nice Work!

You did it! Your Java Swing grade planner now calculates completed semester grades or predicts the Finals score needed for a chosen target.

You turned a real student decision into a tested desktop app with reusable grade rules. Friendly validation keeps every result trustworthy.

You've learned how to:

  • Build a working desktop grade planner in Eclipse IDE that calculates completed semester grades. Add a prediction mode for a blank Finals score.
  • Apply object-oriented design by separating GradeCalculator from GradeCalculatorApp. Protect score calculations with input validation plus exception handling. Show friendly dialogs for unsafe input.
  • Document the configured formula in README.md. Record clear run instructions. Verify the app against five test cases. Explain the Java fundamentals through a quiz.
  • Secret Mission: Extend the model with a custom target grade. Pass that target through the desktop form. Keep 60.0 as the default. Preserve the original five test results.

Ready to quiz yourself?