-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathConverterGUI.java
661 lines (594 loc) · 27.7 KB
/
ConverterGUI.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.text.DecimalFormat;
/** This class contains the graphical interface (hence the extending of JFrame) through which the user can convert a number between temperatures, hence the name.
* @author Miles (amn35)
* @version 06-08-2021
*/
public class ConverterGUI extends JFrame{
/**
* 'df' is a handler for formatting text input as decimal.
*/
static DecimalFormat df = new DecimalFormat("#.#");
private FloatInputPad inputTag = new FloatInputPad();
public static String goodChars = "0123456789.-";
/**
* Constructs an instance of the graphical interface when called. All elements, comments or text mentioning a "window" from here on is in reference to this one interface.
*/
public ConverterGUI()
{
//Object & element names;
// entryCelsius: radio button in menu.
// entryFaren: same button but for Fahrenheit.
// menuScale: dropdown button for Scale containing entryFaren & entryCelsius.
// entryExit: menu item button to close the program.
// menuFile: dropdown button for File containing entryExit.
// entryHelp: menu item button for instruction alert.
// (Note-to-self) add a separator!
// entryAbout: button for info. ("Temperature Converter by Miles")
// menuHelp: dropdown button for Help containing entryHelp & entryAbout.
/**
* The following method will set a suitable minimum size for the GUI window so that the user cannot warp it down to a smaller size.
*/
setMinimumSize(new Dimension(600, 300));
/**
* The following method sets a defined size and position for the window to take when the program loads.
*/
setBounds(10, 10, 600, 300);
/**
* The following method sets a trigger for the program to be able to close by the user's input command (such as the red "X" button in any Microsoft Windows window).
*/
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
/**
* The following method sets the name given to the program, which usually displays as a title across the top border pane of the window when the program loads.
*/
setTitle("Miles's Temperature Converter");
/**
* The following programming instructions create a menu bar and generate it.
*/
JMenuBar menubar = new JMenuBar();
setJMenuBar(menubar);
/**
* The following programming instructions will create a dropdown menu called "File" with an entry called "Quit" and add them to the menu bar.
*/
JMenu menuFile = new JMenu("File");
menubar.add(menuFile);
JMenuItem entryQuit = new JMenuItem("Quit");
menuFile.add(entryQuit);
/**
* The following method sets a trigger for when the menu item "Quit" is selected which will cause the window to close as normal.
*/
entryQuit.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
/**
* The following programming instructions will create a dropdown menu called "Scale" with 2 entries named "Celsius" and "Fahrenheit", proceeding to add them to the menu bar. The 2 items have visual indicators to show whether they're active, and note that Celsius is selected/set to active here while Fahrenheit isn't.
*/
JMenu menuScale = new JMenu("Scale");
menubar.add(menuScale);
JRadioButtonMenuItem entryCelsius = new JRadioButtonMenuItem("Celsius");
//Again, note this statement which sets Celsius as selected.
entryCelsius.setSelected(true);
menuScale.add(entryCelsius);
JRadioButtonMenuItem entryFaren = new JRadioButtonMenuItem("Fahrenheit");
menuScale.add(entryFaren);
/**
* The following programming instructions will create a dropdown menu called "Help" containing 2 separated entries named "Instruction" and "About", and adds them to the menu bar. This block of programming instructions will also set triggers for each item such that selecting either item with spawn an alert box with relevant text on it.
*/
JMenu menuHelp = new JMenu("Help");
menubar.add(menuHelp);
JMenuItem entryHelp = new JMenuItem("Instruction");
menuHelp.add(entryHelp);
//Alert box pop-up.
entryHelp.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(rootPane, "This temperature converter is designed so that you can\nuse it without typing or use it on a tablet\nif you don't have a desktop. Just remember to first set the temperature scale\nyou want to convert from, type in the number you want to convert,\nthen finally select the temperature scale you wish to convert it to.\nIf you don't use backspace and you've made a mistake typing\nin the number you want, you can click the \"Clear\" button\non the pad on-screen to reset the number you typed back to\n\"0\" so that you can type it again. Thanks for using my program.");
}
});
//ADDS SEPARATOR HERE!!
menuHelp.addSeparator();
JMenuItem entryAbout = new JMenuItem("About");
menuHelp.add(entryAbout);
entryAbout.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(rootPane, "A Temperature Conversion Calculator by Miles-THugo");
}
});
//celsButton: Convert to Celsius
//farenButton: Convert to Fahrenheit
//metricNote: text indicating metric
//value: label strip input text
//convertFlow: conversion buttons
//labelFlow: value and metric text
//labelPanel: labelFlow and convertFlow
//numpad: individual button element
//decimLButton: individual button element
//minusButton: individual button element
//clearButton: individual button element
//numpadPanel: numPad, minusButton and clearButton
//inputTag: instance of FloatInputPad
//getThatTemp: instance of Temperature
/**
* From here on, all GUI objects and elements will be prepared together before being added to the window as opposed to being added immediately after the instruction defining it.
*/
/**
* The following programming instructions will create a GUI panel made to occupy the window using a grid-formatted layout manager. "labelPanel" is simply the panel containing the 2 flow panels that represent the temperature label and the scale buttons.
*/
JPanel labelPanel = new JPanel();
labelPanel.setLayout(new GridLayout(2, 1, 10, 10));
JPanel convertFlow = new JPanel();
JPanel labelFlow = new JPanel();
/**
* The following programming instructions will create a text field which functions as the temperature label where the user will type the number they want (setting the digit limit to 25 characters and making the text read "0"), as well as a label which is a piece of text right next to the text box that remains visible, serving to indicate the current temperature scale. There are also instructions here that create 2 buttons reading "Convert to Celsius" and "Convert to Fahrenheit".
*/
JTextField value = new JTextField("0", 25);
JLabel metricNote = new JLabel();
JButton celsButton = new JButton("Convert to Celsius");
JButton farenButton = new JButton("Convert to Fahrenheit");
/**
* The following programming instructions will set metricNote so that "°C" is labelled next to the text box, will disable the "Convert to Celsius" button, and enable the "Convert to Fahrenheit" button. This is written here so that when the program loads, these settings take effect immediately.
*/
farenButton.setEnabled(true);
celsButton.setEnabled(false);
metricNote.setText("°C");
/**
* "0" button
*/
JButton numpad0 = new JButton("0");
numpad0.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
contains0Action(numpad0, value, numpad0);
}
});
/**
* Decimal button
*/
JButton decimLButton = new JButton(".");
decimLButton.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
String text = value.getText();
text = text + decimLButton.getText();
value.setText(text);
decimLButton.setEnabled(false);
numpad0.setEnabled(true);
}
});
/**
* The next several instructions written from here on all relate to making the temperature conversions happen to not only change the text in the temperature label, but also change the state of the buttons and the menu items under "Scale". 2 methods (namely "changeToCels()" and "changeToFaren()") will be made specifically for these actions to reduce code duplication, and they will be called in order to apply these conversions in relation to the relevant GUI objects.
*/
/**
* The following programming instructions will add functionality to the "Convert to Celsius" button. The instructions here should be familiar as they have been used & described above.
*/
celsButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
changeToCels(metricNote, value, farenButton, celsButton, entryCelsius, entryFaren, decimLButton);
}
});
/**
* The following programming instructions will add functionality to the "Celsius" item from the "Scale" menu. The instructions here should be familiar as they have already been used & are aforementioned.
*/
entryCelsius.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
changeToCels(metricNote, value, farenButton, celsButton, entryCelsius, entryFaren, decimLButton);
}
});
/**
* The following programming instructions will add functionality to the "Convert to Fahrenheit" button. The instructions here should be familiar as they have already been used & are aforementioned.
*/
farenButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
changeToFaren(metricNote, value, farenButton, celsButton, entryCelsius, entryFaren, decimLButton);
}
});
/**
* The following programming instructions will add functionality to the "Fahrenheit" item from the "Scale" menu. The instructions here should be familiar as they have already been used & are aforementioned.
This is the last of the several instructions previously mentioned.
*/
entryFaren.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
changeToFaren(metricNote, value, farenButton, celsButton, entryCelsius, entryFaren, decimLButton);
}
});
/**
* The following programming instructions will add, in a particular order, the GUI objects to the panel dedicated for the label now that they've been fully programmed.
First the text box is added to the labelFlow object, then the Scale indicator text is added to it afterward so that they remain next to each other in proper order. The "Convert to Celsius" button is added to the convertFlow object before the "Convert to Fahrenheit" button. Then finally the convertFlow object is added to the panel dedicated to the input label before the labelFlow object is, so the conversion buttons remain above the temperature label.
That wraps up the label panel, so a separate panel for the number pad buttons will follow.
*/
labelFlow.add(value);
labelFlow.add(metricNote);
convertFlow.add(celsButton);
convertFlow.add(farenButton);
labelPanel.add(convertFlow);
labelPanel.add(labelFlow);
/**
* The following programming instructions will create a GUI panel, from a grid-formatted layout manager, that will occupy the window. "numpadPanel" is the panel containing the number pad buttons from which the user can type in a value to convert.
*/
JPanel numpadPanel = new JPanel();
numpadPanel.setLayout(new GridLayout(5, 3, 2, 2));
/**
* The following programming instructions create a row of buttons on the number pad from 7 to 9, and also program them to change the temperature label appropriately when pressed. Then for each button programmed, there's a final instruction that adds each single button to the numpad panel.
*/
for(int i = 7; i <=9; i++) {
JButton numpad = new JButton(""+i);
numpad.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
contains0Action(numpad, value, numpad0);
}
});
numpadPanel.add(numpad);
}
/**
* The following programming instructions do exactly the same thing as the previous set of instructions, but for a new row of buttons from 4 to 6.
*/
for(int i = 4; i <=6; i++) {
JButton numpad = new JButton(""+i);
numpad.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
contains0Action(numpad, value, numpad0);
}
});
numpadPanel.add(numpad);
}
/**
* The following programming instructions do exactly the same thing as the previous set of instructions, but for a new row of buttons from 1 to 3.
*/
for(int i = 1; i <=3; i++) {
JButton numpad = new JButton(""+i);
numpad.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
contains0Action(numpad, value, numpad0);
}
});
numpadPanel.add(numpad);
}
/**
* ((Minus button)) The following programming instructions do exactly the same thing as the previous set of instructions, but for a new row of buttons from 1 to 3.
*/
JButton minusButton = new JButton("-");
minusButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String text = value.getText();
if(text.contains("-")) {
String new_text = text.replace("-", "");
value.setText(new_text);
} else {
text = minusButton.getText() + text;
value.setText(text);
}
}
});
numpadPanel.add(minusButton);
/**
* "0" button.
*/
// Code
numpadPanel.add(numpad0);
/**
* The following pair of programming instructions will set the temperature label to "0", and ensure the "0" button is disabled in this state. As it's written here, this will take effect the moment the user loads the program.
*/
value.setText("0");
numpad0.setEnabled(false);
/*/**
* Decimal button
*/
// code
numpadPanel.add(decimLButton);
/**
* Clear
*/
JButton clearButton = new JButton("Clear");
clearButton.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
value.setText("0");
decimLButton.setEnabled(true);
numpad0.setEnabled(false);
}
});
numpadPanel.add(clearButton);
value.addKeyListener(new KeyListener(){
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
if(!(value.getText()).contains(".")) {
decimLButton.setEnabled(true);
} else {
decimLButton.setEnabled(false);
}
//Now for "0" button.
if(!(value.getText()).startsWith("0")) {
numpad0.setEnabled(true);
} else {
numpad0.setEnabled(false);
/*String new_text = value.getText().replace("0", "");
value.setText(new_text);*/
//value.setText("0"); -- Maybe we don't need to force the typing of 0s.
}
//Proof-of-concept to ignore non-numerical characters (keep "-" though).
/* if(value.getText().contains(goodChars)) {
__
} else {
__
/*String new_text = value.getText().replace("0", "");
value.setText(new_text);/
//value.setText("0");
} */
}
@Override
public void keyReleased(KeyEvent e) {
if(!(value.getText()).contains(".")){
decimLButton.setEnabled(true);
} else {
decimLButton.setEnabled(false);
}
//Now for "0" button.
if(!(value.getText()).startsWith("0")) {
numpad0.setEnabled(true);
} else {
numpad0.setEnabled(false);
//value.setText("0");
}
}
});
this.add(labelPanel, BorderLayout.NORTH);
this.add(numpadPanel, BorderLayout.CENTER);
}
/**
* Main method. Intialises the GUI window.
*/
public static void main (String[] args)
{
ConverterGUI gui = new ConverterGUI();
gui.setVisible(true);
}
/**
* The instructions in this method will invert the states of the conversion buttons as well as the Scale menu items, change the reading next to the temperature label to "°C", calculate the conversion of the input number from Fahrenheit to Celsius, and then replace the text on the temperature label input with the result.
*/
private void changeToCels(JLabel metricNote, JTextField value, JButton farenButton, JButton celsButton, JMenuItem entryCelsius, JMenuItem entryFaren, JButton decimLButton) {
farenButton.setEnabled(true);
celsButton.setEnabled(false);
entryCelsius.setSelected(true);
entryFaren.setSelected(false);
metricNote.setText("°C");
/**
* Handler to make use of input registry methods from FloatInputPad (rather than
* using 'Double.parseDouble()'.
*/
// this.inputTag.splitInput(value.getText());
try{
this.inputTag.splitInput(value.getText());
}catch (java.lang.NumberFormatException emptyString){
System.out.println("Apparently your input is empty...");
value.setText("0");
decimLButton.setEnabled(true);
}
/**
* "farenReading" is simply a variable used to store the number in the temperature label in the case where the temperature is about to go through Celsius conversion. "finalValue" simply stores the result of the conversion and replaces the text in the temperature label with it.
*/
double farenReading = this.inputTag.getTempInput();//CHANGE IT TO USE THE FLOATINPUTPAD!
Temperature getThatTemp = new Temperature(farenReading);
double finalValue = getThatTemp.convertToCelsius();
value.setText(String.valueOf(df.format(finalValue)));
}
private void changeToFaren(JLabel metricNote, JTextField value, JButton farenButton, JButton celsButton, JMenuItem entryCelsius, JMenuItem entryFaren, JButton decimLButton) {
farenButton.setEnabled(false);
celsButton.setEnabled(true);
entryCelsius.setSelected(false);
entryFaren.setSelected(true);
metricNote.setText("°F");
try{
this.inputTag.splitInput(value.getText());
}catch (java.lang.NumberFormatException emptyString){
System.out.println("Apparently your input is empty...");
value.setText("0");
decimLButton.setEnabled(true);
}
/**
* "celsReading" is simply a variable used to store the number in the temperature label in the case where the temperature is about to go through Fahrenheit conversion.
*/
double celsReading = this.inputTag.getTempInput();
Temperature getThatTemp = new Temperature(celsReading);
double finalValue = getThatTemp.convertToFaren();
value.setText(String.valueOf(df.format(finalValue)));
}
/**
* The instructions in this method tell the program what to do if a numerical numpad button is pressed depending on if the temperature label reads "0" or not.
*/
private void contains0Action(JButton numpad, JTextField value, JButton numpad0) {
/**
* "text" is simply a temporary variable for the value in the temperature label.
*/
String text = value.getText();
if(text.equals("0")) {
text = numpad.getText();
if(text != "0"){
value.setText(text);
numpad0.setEnabled(true);
}else{
numpad0.setEnabled(false);
}
} else {
if(text == "" && numpad.getText() == "0"){
text = numpad.getText();
value.setText(text);
numpad0.setEnabled(false);
}else{
text = text + numpad.getText();
value.setText(text);
numpad0.setEnabled(true);
}
}
}
}
/** This class is intended for overall input handling.
* It is displayed purely as a proof-of-concept.
*/
class FloatInputPad{
private String inputRegister;
private double inputLogged = 0;
private String[] splitUp;
private String tempLabel = "0";
//So...if Celsius is already selected, the user shouldn't be about to press it again. Sigh...great.
private boolean returnFlag = false;
public FloatInputPad(String a){
//Splitting done here.
//Now call method for storing input as a particular temperature.
splitInput(a);
}
public FloatInputPad(String a, boolean b){
splitInput(a, b);
}
//Made to allow for use locally in another class, so other methods can be used manually rather than once automatically.
public FloatInputPad(){
}
public void splitInput(String a)
{
if(a.contains(".")){
this.splitUp = a.split(".");
writeInput(this.splitUp);
}else{
this.inputRegister = "";
for(int i = 0; i<a.length(); i++){
this.inputRegister = this.inputRegister + a.charAt(i);
}
logInput();
}
//For loop for this method alone (so you can remove writeInput method), just in case for some reason the for each loop doesn't work.
/*
for(int i = 0; i < this.splitUp.length; i++)
{
if(i == 0){
this.inputRegister = this.splitUp[i];
}else{
this.inputRegister = this.inputRegister + this.splitUp[i];
}
}*/
}
public void splitInput(String a, boolean b)
{
this.returnFlag = true;
this.splitUp = a.split(".");
writeInput(this.splitUp);
}
private void writeInput(String[] a)
{
this.inputRegister = "";
for(String x: a){
this.inputRegister = this.inputRegister + x;
//System.out.println(this.inputRegister);
}
if(this.returnFlag == true){
logInput(this.returnFlag);
this.returnFlag = false;
}else{
logInput();
}
}
private void logInput()
{
this.inputLogged = Double.parseDouble(this.inputRegister);
}
private double logInput(boolean a)
{
this.inputLogged = Double.parseDouble(this.inputRegister);
return this.inputLogged;
}
public double getTempInput()
{
return this.inputLogged;
}
}
/** Class made to refer to for arithmetic process of converting
* between °Celsius and °Fahrenheit scale metrics. */
class Temperature{
/** Variable "reading" used for calculations. */
private double reading = 0;
/** A flag simply to indicate the metric of the value
* stored. Made for testing stages of class.
* False == Fahrenheit. */
private boolean metric = true;
//False == Fahrenheit.
public Temperature(double n){
this.reading = n;
}
/*public Temperature(String a){
FloatInputPad.splitInput(a);
} In case I integrate the text box with the actual splitInput() function. Temporarily here for me to figure out later.*/
/* Just in case I can't set it any other way for some
reason, this sets the temperature value. */
public void setTemperature(double n){
this.reading = n;
}
/* Returns the temperature value. */
public double getTemperature(){
return this.reading;
}
/** The following method processes a number using an
* equation made to convert to °Celsius. */
public double convertToCelsius(double x)
{
/** "meter" is a temporary variable used in this
* class's methods to store conversion results. */
double meter = ((x - 32) / 1.8);
this.reading = meter;
this.metric = true;
return meter;
}
/** Processes the stored value using an equation made to
* convert to °Celsius. */
public double convertToCelsius()
{
double meter = ((this.reading - 32) / 1.8);
this.reading = meter;
this.metric = true;
return meter;
}
/** Processes a number using an equation made to
* convert to °Fahrenheit. */
public double convertToFaren(double x)
{
double meter = (x * 1.8) + 32;
this.reading = meter;
this.metric = false;
return meter;
}
/** Processes the stored value using an equation made to
* convert to °Fahrenheit. */
public double convertToFaren()
{
double meter = (this.reading * 1.8) + 32;
this.reading = meter;
this.metric = false;
return meter;
}
/** Separate method made to set the temperature to
* °Celsius just in case I needed it. */
private void setToCelsius(){
this.metric = true;
//System.out.println("Temperature is now in °Celsius.");
}
/** Separate method made to set the temperature to
* °Fahrenheit just in case I needed it. */
private void setToFaren(){
this.metric = false;
//System.out.println("Temperature is now in °Fahrenheit.");
}
}