Source of GradeCalculatorApp_1.java


  1: import javafx.application.Application;
  2: import javafx.application.Platform;
  3: import javafx.geometry.Insets;
  4: import javafx.geometry.Pos;
  5: import javafx.scene.Node;
  6: import javafx.scene.Scene;
  7: import javafx.scene.control.Button;
  8: import javafx.scene.control.Label;
  9: import javafx.scene.control.TextField;
 10: import javafx.scene.layout.GridPane;
 11: import javafx.scene.layout.Pane;
 12: import javafx.scene.text.Font;
 13: import javafx.stage.Stage;

 15: /**
 16:  * The Application version of the first Grade Calculator Program.
 17:  *
 18:  * @author Mark Young (A00000000)
 19:  */
 20: public class GradeCalculatorApp_1 extends Application {

 22:     // weights for the course components
 23:     public static final double ASGN_WEIGHT = 25.0;
 24:     public static final double LABS_WEIGHT = 15.0;
 25:     public static final double TEST_WEIGHT = 20.0;
 26:     public static final double EXAM_WEIGHT = 30.0;
 27:     public static final double BEST_WEIGHT = 10.0;

 29:     // TextField variables -- so theEventHandler can refer to them.
 30:     private TextField asgnField;
 31:     private TextField labsField;
 32:     private TextField testField;
 33:     private TextField examField;
 34:     private TextField courseGradeField;

 36:     // Font for the text in the scene
 37:     private static final double FONT_SIZE = 24.0;
 38:     private static final Font LABEL_FONT = Font.font(STYLESHEET_MODENA, 
 39:             FONT_SIZE);
 40:     private static final Font FIELD_FONT = Font.font("monospace", FONT_SIZE);

 42:     // gap sizes in grid layout
 43:     public static final int BIG = 25;
 44:     public static final int MEDIUM = 15;
 45:     public static final int SMALL = 10;

 47:     /**
 48:      * Do everything necessary to get the Application started.
 49:      *
 50:      * @param theStage the inside part of the window the App runs in
 51:      */
 52:     @Override
 53:     public void start(Stage theStage) {
 54:         Pane theScenery = createScenery();
 55:         Scene theScene = new Scene(theScenery);

 57:         theStage.setTitle("Grade Calculator App #1");
 58:         theStage.setScene(theScene);
 59:         theStage.sizeToScene();
 60:         theStage.show();
 61:     }

 63:     /**
 64:      * @param args IGNORED
 65:      */
 66:     public static void main(String[] args) {
 67:         launch(args);
 68:     }

 70:     /**
 71:      * Create and lay out all the labels, fields, buttons, etc. required in this
 72:      * Application's one scene.
 73:      *
 74:      * @return a Pane containing all the labels, fields and buttons required for
 75:      *         this Application's one Scene.
 76:      */
 77:     private Pane createScenery() {
 78:         GridPane grid = new GridPane();
 79:         grid.setPadding(new Insets(MEDIUM, BIG, MEDIUM, BIG));
 80:         grid.setHgap(MEDIUM);
 81:         grid.setVgap(SMALL);

 83:         // create text fields
 84:         asgnField = makeNumberField();
 85:         labsField = makeNumberField();
 86:         testField = makeNumberField();
 87:         examField = makeNumberField();
 88:         courseGradeField = makeNumberField();
 89:         courseGradeField.setEditable(false);

 91:         // create buttons
 92:         Button calculate = makeButton("Calculate");
 93:         Button done = makeButton("Quit");

 95:         // activate buttons
 96:         calculate.setOnAction(click -> calculateGrade());
 97:         done.setOnAction(click -> exitProgram());
 98:         calculate.setDefaultButton(true);

100:         // arrange the scenery in a grid pattern
101:         grid.add(makeLabel("Enter your percentage grades."), 0, 0, 2, 1);
102:         grid.addRow(0);
103:         grid.addRow(1, makeLabel("Assignments:"), asgnField);
104:         grid.addRow(2, makeLabel("Labs:"), labsField);
105:         grid.addRow(3, makeLabel("Tests:"), testField);
106:         grid.addRow(4, makeLabel("Exam:"), examField);
107:         grid.addRow(5, makeLabel("Course:"), courseGradeField);
108:         grid.addRow(6, calculate, done);
109:         GridPane.setFillWidth(calculate, true);
110:         GridPane.setFillWidth(done, true);

112:         return grid;
113:     }

115:     /**
116:      * Make a field suitable for holding numeric values. In particular, in
117:      * should have a large, fixed-width font and be aligned to the right.
118:      *
119:      * @return a text field suitable for holding numbers.
120:      */
121:     private TextField makeNumberField() {
122:         TextField f = new TextField();
123:         f.setFont(FIELD_FONT);
124:         f.setAlignment(Pos.CENTER_RIGHT);
125:         return f;
126:     }

128:     /**
129:      * Make a button suitable for the application. In particular, it should have
130:      * a large font and it should be able to stretch to fill the grid cell it
131:      * has been placed in.
132:      *
133:      * @param label the text label to appear on the button
134:      * @return a button formatted for this application
135:      */
136:     private Button makeButton(String label) {
137:         Button b = new Button();
138:         b.setText(label);
139:         b.setFont(LABEL_FONT);
140:         b.setMaxWidth(Double.MAX_VALUE);
141:         return b;
142:     }

144:     /**
145:      * Make a label suitable for the application. In particular, it should have
146:      * a large font.
147:      *
148:      * @param text the text to appear in the label
149:      * @return a label suitable for this application
150:      */
151:     private Node makeLabel(String text) {
152:         Label l = new Label();
153:         l.setText(text);
154:         l.setFont(LABEL_FONT);
155:         return l;
156:     }

158:     /**
159:      * Get the numeric value from a field.
160:      *
161:      * @param field the field to get the numeric value from
162:      * @return the numeric value of the text in the given field
163:      * @throws NumberFormatException if the text isn't a valid number
164:      */
165:     private double getValue(TextField field) {
166:         return Double.parseDouble(field.getText());
167:     }

169:     /**
170:      * Put the given numeric value into the given field.
171:      *
172:      * @param field the field to put the value in
173:      * @param value the value to place into the field
174:      */
175:     private void setValue(TextField field, double value) {
176:         field.setText(Double.toString(value));
177:     }

179:     /**
180:      * Calculate-button handler. Calculate the course grade by combining the
181:      * component scores according to their weights. Store the result in the
182:      * course grade field.
183:      *
184:      * NOTE: this method will fail without notice if any of the component fields
185:      * have invalid data.
186:      */
187:     private void calculateGrade() {
188:         // create the required variables
189:         double asgnGrade, labsGrade, testGrade, examGrade, bestGrade, 
190:                 courseGrade;

192:         // get the components of the course grade
193:         asgnGrade = getValue(asgnField);
194:         labsGrade = getValue(labsField);
195:         testGrade = getValue(testField);
196:         examGrade = getValue(examField);
197:         bestGrade = Math.max(testGrade, examGrade);

199:         // calculate the course grade
200:         courseGrade = (ASGN_WEIGHT * asgnGrade
201:                 + LABS_WEIGHT * labsGrade
202:                 + TEST_WEIGHT * testGrade
203:                 + EXAM_WEIGHT * examGrade
204:                 + BEST_WEIGHT * bestGrade)
205:                 / 100.0;

207:         // display the course grade to the user
208:         setValue(courseGradeField, courseGrade);
209:     }

211:     /**
212:      * Quit-button handler. Exit the program safely.
213:      */
214:     private void exitProgram() {
215:         Platform.exit();
216:     }

218: }