Source of GradeCalculatorApp.java


  2: import java.awt.BorderLayout;
  3: import java.awt.Component;
  4: import java.awt.FlowLayout;
  5: import java.awt.Font;
  6: import java.awt.GridLayout;
  7: import java.awt.Insets;
  8: import javax.swing.JButton;
  9: import javax.swing.JFrame;
 10: import javax.swing.JLabel;
 11: import javax.swing.JPanel;
 12: import javax.swing.JTextField;
 13: import javax.swing.border.Border;
 14: import javax.swing.border.EmptyBorder;

 16: /**
 17:  * A Swing application to calculate course grades. 
 18:  * 
 19:  * @author Mark Young (A00000000)
 20:  */
 21: public class GradeCalculatorApp extends JFrame {

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

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

 37:     // Font for the text in the scene
 38:     private static final double FONT_SIZE = 20.0;

 40:     // gap sizes in grid layout
 41:     private static final int BIG = 20;
 42:     private static final int MEDIUM = 5;
 43:     private static final int SMALL = 2;
 44:     private static final Border EMPTY = new EmptyBorder(5, 5, 5, 5);

 46:     public GradeCalculatorApp() {
 47:         super("Grade Calculator");
 48:         this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 49:         setLocationRelativeTo(null);

 51:         // create top panel
 52:         JPanel top = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0));
 53:         top.setBorder(EMPTY);
 54:         top.add(makeLabel("Enter your percentage grades:"));
 55:         // create middle panel
 56:         JPanel middle = new JPanel(new GridLayout(MEDIUM, SMALL, 0, BIG));
 57:         middle.setBorder(EMPTY);
 58:         asgnField = makeField();
 59:         labsField = makeField();
 60:         testField = makeField();
 61:         examField = makeField();
 62:         courseGradeField = makeField();
 63:         courseGradeField.setEditable(false);

 65:         middle.add(makeLabel("Assignments:"));
 66:         middle.add(asgnField);
 67:         middle.add(makeLabel("Labs:"));
 68:         middle.add(labsField);
 69:         middle.add(makeLabel("Tests:"));
 70:         middle.add(testField);
 71:         middle.add(makeLabel("Exam:"));
 72:         middle.add(examField);
 73:         middle.add(makeLabel("Course Grade:"));
 74:         middle.add(courseGradeField);

 76:         // create bottom panel
 77:         JPanel bottom = new JPanel(new FlowLayout(FlowLayout.CENTER, BIG, 0));
 78:         bottom.setBorder(EMPTY);
 79:         JButton addButton = makeButton("Calculate");
 80:         JButton doneButton = makeButton("Quit");
 81:         addButton.addActionListener(e
 82:                 -> calculateGrade()
 83:         );
 84:         doneButton.addActionListener(e -> System.exit(0));
 85:         bottom.add(addButton);
 86:         bottom.add(doneButton);

 88:         // add panels to window
 89:         add(top, BorderLayout.NORTH);       // or PAGE_START
 90:         add(middle, BorderLayout.CENTER);   // or leave out (default)
 91:         add(bottom, BorderLayout.SOUTH);    // or PAGE_END
 92:         pack();
 93:     }

 95:     /**
 96:      * @param args the command line arguments
 97:      */
 98:     public static void main(String[] args) {
 99:         GradeCalculatorApp win = new GradeCalculatorApp();
100:         win.setVisible(true);
101:     }

103:     /**
104:      * Calculate-button handler. Calculate the course grade by combining the
105:      * component scores according to their weights. Store the result in the
106:      * course grade field.
107:      *
108:      * NOTE: this method will fail without notice if any of the component fields
109:      * have invalid data.
110:      */
111:     private void calculateGrade() {
112:         // create the required variables
113:         double asgnGrade, labsGrade, testGrade, examGrade, bestGrade,
114:                 courseGrade;

116:         // get the components of the course grade
117:         asgnGrade = getValue(asgnField);
118:         labsGrade = getValue(labsField);
119:         testGrade = getValue(testField);
120:         examGrade = getValue(examField);
121:         bestGrade = Math.max(testGrade, examGrade);

123:         // calculate the course grade
124:         courseGrade = (ASGN_WEIGHT * asgnGrade
125:                 + LABS_WEIGHT * labsGrade
126:                 + TEST_WEIGHT * testGrade
127:                 + EXAM_WEIGHT * examGrade
128:                 + BEST_WEIGHT * bestGrade)
129:                 / 100.0;

131:         // display the course grade to the user
132:         setValue(courseGradeField, courseGrade);
133:     }

135:     /**
136:      * Get the numeric value from a field.
137:      *
138:      * @param field the field to get the numeric value from
139:      * @return the numeric value of the text in the given field
140:      * @throws NumberFormatException if the text isn't a valid number
141:      */
142:     private double getValue(JTextField field) {
143:         return Double.parseDouble(field.getText());
144:     }

146:     /**
147:      * Put the given numeric value into the given field.
148:      *
149:      * @param field the field to put the value in
150:      * @param value the value to place into the field
151:      */
152:     private void setValue(JTextField field, double value) {
153:         field.setText(Double.toString(value));
154:     }

156:     /**
157:      * Create a text field specialized to hold numbers.
158:      *
159:      * @return a right-justified text field with internal padding
160:      */
161:     private static JTextField makeField() {
162:         JTextField result = new JTextField();

164:         // style the field
165:         resizeFont(result, FONT_SIZE);
166:         result.setHorizontalAlignment(JTextField.TRAILING);
167:         result.setMargin(new Insets(5, 5, 5, 5));

169:         return result;
170:     }

172:     /**
173:      * Create a text field specialized to hold numbers.
174:      *
175:      * @return a right-justified text field with internal padding
176:      */
177:     private static JLabel makeLabel(String text) {
178:         JLabel result = new JLabel(text);

180:         // style the field
181:         resizeFont(result, FONT_SIZE);

183:         return result;
184:     }

186:     /**
187:      * Create a text field specialized to hold numbers.
188:      *
189:      * @return a right-justified text field with internal padding
190:      */
191:     private static JButton makeButton(String text) {
192:         JButton result = new JButton(text);

194:         // style the field
195:         resizeFont(result, FONT_SIZE);

197:         return result;
198:     }

200:     /**
201:      * Change the font size to a fixed value in a container and all its
202:      * components.
203:      *
204:      * @param c the container to change the font size in
205:      * @param size the size to change it to
206:      */
207:     public static void resizeFont(Component c, double size) {
208:         Font myFont = c.getFont();
209:         if (myFont != null) {
210:             c.setFont(myFont.deriveFont((float) size));
211:         }
212:     }

214: }