public class GradeCalculatorApp extends JFrame
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: }